diff --git a/Cargo.lock b/Cargo.lock index 75c6ab37bd14f..7765353092553 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,7 +43,7 @@ dependencies = [ "cfg-if", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -567,7 +567,7 @@ dependencies = [ "termize", "tokio", "toml 0.7.8", - "ui_test", + "ui_test 0.26.5", "walkdir", ] @@ -1442,7 +1442,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", ] [[package]] @@ -2342,18 +2354,18 @@ dependencies = [ "chrono-tz", "colored", "directories", - "getrandom", + "getrandom 0.3.1", "libc", "libffi", "libloading", "measureme", - "rand", + "rand 0.9.0", "regex", "rustc_version", "smallvec", "tempfile", "tikv-jemalloc-sys", - "ui_test", + "ui_test 0.28.0", "windows-sys 0.52.0", ] @@ -2782,7 +2794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ "phf_shared 0.10.0", - "rand", + "rand 0.8.5", ] [[package]] @@ -2792,7 +2804,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared 0.11.3", - "rand", + "rand 0.8.5", ] [[package]] @@ -2860,7 +2872,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -2978,8 +2990,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.0", + "zerocopy 0.8.14", ] [[package]] @@ -2989,7 +3012,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.0", ] [[package]] @@ -2998,7 +3031,17 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom 0.3.1", + "zerocopy 0.8.14", ] [[package]] @@ -3007,7 +3050,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3045,7 +3088,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror 1.0.69", ] @@ -3283,7 +3326,7 @@ name = "rustc_abi" version = "0.0.0" dependencies = [ "bitflags", - "rand", + "rand 0.8.5", "rand_xoshiro", "rustc_data_structures", "rustc_feature", @@ -3897,7 +3940,7 @@ dependencies = [ name = "rustc_incremental" version = "0.0.0" dependencies = [ - "rand", + "rand 0.8.5", "rustc_ast", "rustc_data_structures", "rustc_errors", @@ -5218,7 +5261,7 @@ checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", - "getrandom", + "getrandom 0.2.15", "once_cell", "rustix", "windows-sys 0.59.0", @@ -5281,8 +5324,8 @@ version = "0.1.0" dependencies = [ "indicatif", "num", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "rayon", ] @@ -5602,7 +5645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", - "rand", + "rand 0.8.5", "static_assertions", ] @@ -5662,6 +5705,32 @@ dependencies = [ "spanned", ] +[[package]] +name = "ui_test" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576" +dependencies = [ + "annotate-snippets 0.11.5", + "anyhow", + "bstr", + "cargo-platform", + "cargo_metadata 0.18.1", + "color-eyre", + "colored", + "comma", + "crossbeam-channel", + "indicatif", + "levenshtein", + "prettydiff", + "regex", + "rustc_version", + "rustfix", + "serde", + "serde_json", + "spanned", +] + [[package]] name = "unic-langid" version = "0.9.5" @@ -5843,7 +5912,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -5880,6 +5949,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasi-preview1-component-adapter-provider" version = "29.0.1" @@ -6475,6 +6553,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956" +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + [[package]] name = "wit-component" version = "0.223.0" @@ -6584,7 +6671,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" +dependencies = [ + "zerocopy-derive 0.8.14", ] [[package]] @@ -6598,6 +6694,17 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "zerofrom" version = "0.1.5" diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 363b96fdff1f6..57a757f9085ca 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -351,7 +351,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", ] [[package]] @@ -529,12 +541,12 @@ dependencies = [ "chrono-tz", "colored", "directories", - "getrandom", + "getrandom 0.3.1", "libc", "libffi", "libloading", "measureme", - "rand", + "rand 0.9.0", "regex", "rustc_version", "smallvec", @@ -662,7 +674,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -692,7 +704,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -729,19 +741,28 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.0", + "zerocopy 0.8.14", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.0", ] [[package]] @@ -749,8 +770,15 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" dependencies = [ - "getrandom", + "getrandom 0.3.1", + "zerocopy 0.8.14", ] [[package]] @@ -768,7 +796,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror", ] @@ -1051,9 +1079,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ui_test" -version = "0.26.5" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ee4c40e5a5f9fa6864ff976473e5d6a6e9884b6ce68b40690d9f87e1994c83" +checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576" dependencies = [ "annotate-snippets", "anyhow", @@ -1105,6 +1133,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -1244,6 +1281,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -1251,7 +1297,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" +dependencies = [ + "zerocopy-derive 0.8.14", ] [[package]] @@ -1264,3 +1319,14 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zerocopy-derive" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 6e8e270985e07..de80722fc3df1 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -18,8 +18,8 @@ test = false # we have no unit tests doctest = false # and no doc tests [dependencies] -getrandom = { version = "0.2", features = ["std"] } -rand = "0.8" +getrandom = { version = "0.3", features = ["std"] } +rand = "0.9" smallvec = { version = "1.7", features = ["drain_filter"] } aes = { version = "0.8.3", features = ["hazmat"] } measureme = "11" @@ -47,8 +47,8 @@ windows-sys = { version = "0.52", features = [ ] } [dev-dependencies] +ui_test = "0.28.0" colored = "2" -ui_test = "0.26.5" rustc_version = "0.4" regex = "1.5.5" tempfile = "3" diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index fb3fc621565e3..5583030b490ae 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -14,9 +14,7 @@ function endgroup { begingroup "Building Miri" # Global configuration -# We are getting some odd linker warnings on macOS, make sure they do not fail the build. -# (See .) -export RUSTFLAGS="-D warnings -A linker-messages" +export RUSTFLAGS="-D warnings" export CARGO_INCREMENTAL=0 export CARGO_EXTRA_FLAGS="--locked" diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0d405f532fcd8..6e84524c8aa86 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -2f0ad2a71e4a4528bb80bcb24bf8fa4e50cb87c2 +6dd75f0d6802f56564f5f9c947a85ded286d3986 diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 3d0fc5590eb81..a4f2a117b181c 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -217,7 +217,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // We have to pick a fresh address. // Leave some space to the previous allocation, to give it some chance to be less aligned. // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. - let slack = rng.gen_range(0..16); + let slack = rng.random_range(0..16); // From next_base_addr + slack, round up to adjust for alignment. let base_addr = global_state .next_base_addr diff --git a/src/tools/miri/src/alloc_addresses/reuse_pool.rs b/src/tools/miri/src/alloc_addresses/reuse_pool.rs index b0c7ee7dff562..c0d24a9fbbcf9 100644 --- a/src/tools/miri/src/alloc_addresses/reuse_pool.rs +++ b/src/tools/miri/src/alloc_addresses/reuse_pool.rs @@ -58,7 +58,7 @@ impl ReusePool { // We don't remember stack addresses: there's a lot of them (so the perf impact is big), // and we only want to reuse stack slots within the same thread or else we'll add a lot of // undesired synchronization. - if kind == MemoryKind::Stack || !rng.gen_bool(self.address_reuse_rate) { + if kind == MemoryKind::Stack || !rng.random_bool(self.address_reuse_rate) { return; } let clock = clock(); @@ -88,10 +88,10 @@ impl ReusePool { thread: ThreadId, ) -> Option<(u64, Option)> { // Determine whether we'll even attempt a reuse. As above, we don't do reuse for stack addresses. - if kind == MemoryKind::Stack || !rng.gen_bool(self.address_reuse_rate) { + if kind == MemoryKind::Stack || !rng.random_bool(self.address_reuse_rate) { return None; } - let cross_thread_reuse = rng.gen_bool(self.address_reuse_cross_thread_rate); + let cross_thread_reuse = rng.random_bool(self.address_reuse_cross_thread_rate); // Determine the pool to take this from. let subpool = self.subpool(align); // Let's see if we can find something of the right size. We want to find the full range of @@ -118,7 +118,7 @@ impl ReusePool { return None; } // Pick a random element with the desired size. - let idx = rng.gen_range(begin..end); + let idx = rng.random_range(begin..end); // Remove it from the pool and return. let (chosen_addr, chosen_size, chosen_thread, clock) = subpool.remove(idx); debug_assert!(chosen_size >= size && chosen_addr % align.bytes() == 0); diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 988a0be632774..77692ed8655ea 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -723,8 +723,8 @@ fn main() { // Ensure we have parallelism for many-seeds mode. if many_seeds.is_some() && !rustc_args.iter().any(|arg| arg.starts_with("-Zthreads=")) { - // Clamp to 8 threads; things get a lot less efficient beyond that due to lock contention. - let threads = std::thread::available_parallelism().map_or(1, |n| n.get()).min(8); + // Clamp to 10 threads; things get a lot less efficient beyond that due to lock contention. + let threads = std::thread::available_parallelism().map_or(1, |n| n.get()).min(10); rustc_args.push(format!("-Zthreads={threads}")); } let many_seeds = diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index bcc8668dbc122..18a5a0612bb06 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -865,7 +865,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this); let cause = match kind { - RetagKind::TwoPhase { .. } => RetagCause::TwoPhase, + RetagKind::TwoPhase => RetagCause::TwoPhase, RetagKind::FnEntry => unreachable!(), RetagKind::Raw | RetagKind::Default => RetagCause::Normal, }; @@ -880,7 +880,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields; let retag_cause = match kind { - RetagKind::TwoPhase { .. } => unreachable!(), // can only happen in `retag_ptr_value` + RetagKind::TwoPhase => unreachable!(), // can only happen in `retag_ptr_value` RetagKind::FnEntry => RetagCause::FnEntry, RetagKind::Default | RetagKind::Raw => RetagCause::Normal, }; @@ -904,10 +904,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { new_perm: NewPermission, ) -> InterpResult<'tcx> { let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; - let val = self.ecx.sb_retag_reference(&val, new_perm, RetagInfo { - cause: self.retag_cause, - in_field: self.in_field, - })?; + let val = self.ecx.sb_retag_reference( + &val, + new_perm, + RetagInfo { cause: self.retag_cause, in_field: self.in_field }, + )?; self.ecx.write_immediate(*val, place)?; interp_ok(()) } @@ -996,10 +997,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { access: Some(AccessKind::Write), protector: Some(ProtectorKind::StrongProtector), }; - this.sb_retag_place(place, new_perm, RetagInfo { - cause: RetagCause::InPlaceFnPassing, - in_field: false, - }) + this.sb_retag_place( + place, + new_perm, + RetagInfo { cause: RetagCause::InPlaceFnPassing, in_field: false }, + ) } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 5d7c3d8c219f9..5c12ce39d10da 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -379,14 +379,18 @@ pub mod diagnostics { use super::*; impl fmt::Display for PermissionPriv { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", match self { - ReservedFrz { conflicted: false } => "Reserved", - ReservedFrz { conflicted: true } => "Reserved (conflicted)", - ReservedIM => "Reserved (interior mutable)", - Active => "Active", - Frozen => "Frozen", - Disabled => "Disabled", - }) + write!( + f, + "{}", + match self { + ReservedFrz { conflicted: false } => "Reserved", + ReservedFrz { conflicted: true } => "Reserved (conflicted)", + ReservedIM => "Reserved (interior mutable)", + Active => "Active", + Frozen => "Frozen", + Disabled => "Disabled", + } + ) } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index fd69278f20a7f..3389b1c602c33 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -581,15 +581,18 @@ impl Tree { let mut debug_info = NodeDebugInfo::new(root_tag, root_default_perm, span); // name the root so that all allocations contain one named pointer debug_info.add_name("root of the allocation"); - nodes.insert(root_idx, Node { - tag: root_tag, - parent: None, - children: SmallVec::default(), - default_initial_perm: root_default_perm, - // The root may never be skipped, all accesses will be local. - default_initial_idempotent_foreign_access: IdempotentForeignAccess::None, - debug_info, - }); + nodes.insert( + root_idx, + Node { + tag: root_tag, + parent: None, + children: SmallVec::default(), + default_initial_perm: root_default_perm, + // The root may never be skipped, all accesses will be local. + default_initial_idempotent_foreign_access: IdempotentForeignAccess::None, + debug_info, + }, + ); nodes }; let rperms = { @@ -624,14 +627,17 @@ impl<'tcx> Tree { let parent_idx = self.tag_mapping.get(&parent_tag).unwrap(); let strongest_idempotent = default_initial_perm.strongest_idempotent_foreign_access(prot); // Create the node - self.nodes.insert(idx, Node { - tag: new_tag, - parent: Some(parent_idx), - children: SmallVec::default(), - default_initial_perm, - default_initial_idempotent_foreign_access: strongest_idempotent, - debug_info: NodeDebugInfo::new(new_tag, default_initial_perm, span), - }); + self.nodes.insert( + idx, + Node { + tag: new_tag, + parent: Some(parent_idx), + children: SmallVec::default(), + default_initial_perm, + default_initial_idempotent_foreign_access: strongest_idempotent, + debug_info: NodeDebugInfo::new(new_tag, default_initial_perm, span), + }, + ); // Register new_tag as a child of parent_tag self.nodes.get_mut(parent_idx).unwrap().children.push(idx); // Initialize perms diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 4cdc9348dc9f8..b1ca434361b4a 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -830,7 +830,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { let success_rate = 1.0 - this.machine.cmpxchg_weak_failure_rate; let cmpxchg_success = eq.to_scalar().to_bool()? && if can_fail_spuriously { - this.machine.rng.get_mut().gen_bool(success_rate) + this.machine.rng.get_mut().random_bool(success_rate) } else { true }; diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 6d22dd8d68d93..a8a2491304dd1 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -1138,7 +1138,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { use rand::Rng as _; let this = self.eval_context_mut(); - if this.machine.rng.get_mut().gen_bool(this.machine.preemption_rate) { + if this.machine.rng.get_mut().random_bool(this.machine.preemption_rate) { this.yield_active_thread(); } } diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index c8f04e252072e..36b15dbf623da 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -558,15 +558,15 @@ where match chars.next() { Some('"') => { - cmd.extend(iter::repeat('\\').take(nslashes * 2 + 1)); + cmd.extend(iter::repeat_n('\\', nslashes * 2 + 1)); cmd.push('"'); } Some(c) => { - cmd.extend(iter::repeat('\\').take(nslashes)); + cmd.extend(iter::repeat_n('\\', nslashes)); cmd.push(c); } None => { - cmd.extend(iter::repeat('\\').take(nslashes * 2)); + cmd.extend(iter::repeat_n('\\', nslashes * 2)); break; } } diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index c5538351d7dd1..5204056a3d5e9 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -421,7 +421,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.machine.communicate() { // Fill the buffer using the host's rng. - getrandom::getrandom(&mut data) + getrandom::fill(&mut data) .map_err(|err| err_unsup_format!("host getrandom failed: {}", err))?; } else { let rng = this.machine.rng.get_mut(); @@ -678,6 +678,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) } + /// Helper function used inside shims of foreign functions to check that the target OS + /// is one of `target_oses`. It returns an error containing the `name` of the foreign function + /// in a message if this is not the case. + fn check_target_os(&self, target_oses: &[&str], name: Symbol) -> InterpResult<'tcx> { + let target_os = self.eval_context_ref().tcx.sess.target.os.as_ref(); + if !target_oses.contains(&target_os) { + throw_unsup_format!("`{name}` is not supported on {target_os}"); + } + interp_ok(()) + } + /// Helper function used inside the shims of foreign functions to assert that the target OS /// is part of the UNIX family. It panics showing a message with the `name` of the foreign function /// if this is not the case. @@ -991,6 +1002,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { check_arg_count(args) } + /// Check shim for variadic function. + /// Returns a tuple that consisting of an array of fixed args, and a slice of varargs. + fn check_shim_variadic<'a, const N: usize>( + &mut self, + abi: &FnAbi<'tcx, Ty<'tcx>>, + exp_abi: Conv, + link_name: Symbol, + args: &'a [OpTy<'tcx>], + ) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])> + where + &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>, + { + self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?; + check_vargarg_fixed_arg_count(link_name, abi, args) + } + /// Mark a machine allocation that was just created as immutable. fn mark_immutable(&mut self, mplace: &MPlaceTy<'tcx>) { let this = self.eval_context_mut(); @@ -1184,7 +1211,8 @@ where throw_ub_format!("incorrect number of arguments: got {}, expected {}", args.len(), N) } -/// Check that the number of args is at least the minumim what we expect. +/// Check that the number of args is at least the minimum what we expect. +/// FIXME: Remove this function, use varargs and `check_min_vararg_count` instead. pub fn check_min_arg_count<'a, 'tcx, const N: usize>( name: &'a str, args: &'a [OpTy<'tcx>], @@ -1199,6 +1227,51 @@ pub fn check_min_arg_count<'a, 'tcx, const N: usize>( ) } +/// Check that the number of varargs is at least the minimum what we expect. +/// Fixed args should not be included. +/// Use `check_vararg_fixed_arg_count` to extract the varargs slice from full function arguments. +pub fn check_min_vararg_count<'a, 'tcx, const N: usize>( + name: &'a str, + args: &'a [OpTy<'tcx>], +) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { + if let Some((ops, _)) = args.split_first_chunk() { + return interp_ok(ops); + } + throw_ub_format!( + "not enough variadic arguments for `{name}`: got {}, expected at least {}", + args.len(), + N + ) +} + +/// Check the number of fixed args of a vararg function. +/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs. +fn check_vargarg_fixed_arg_count<'a, 'tcx, const N: usize>( + link_name: Symbol, + abi: &FnAbi<'tcx, Ty<'tcx>>, + args: &'a [OpTy<'tcx>], +) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])> { + if !abi.c_variadic { + throw_ub_format!("calling a variadic function with a non-variadic caller-side signature"); + } + if abi.fixed_count != u32::try_from(N).unwrap() { + throw_ub_format!( + "incorrect number of fixed arguments for variadic function `{}`: got {}, expected {N}", + link_name.as_str(), + abi.fixed_count + ) + } + if let Some(args) = args.split_first_chunk() { + return interp_ok(args); + } + throw_ub_format!( + "incorrect number of arguments for `{}`: got {}, expected at least {}", + link_name.as_str(), + args.len(), + N + ) +} + pub fn isolation_abort_error<'tcx>(name: &str) -> InterpResult<'tcx> { throw_machine_stop!(TerminationInfo::UnsupportedInIsolation(format!( "{name} not available when isolation is enabled", diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 9eebbc5d3631e..bce78adcaea45 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -141,7 +141,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // FIXME: should we check for validity here? It's tricky because we do not have a // place. Codegen does not seem to set any attributes like `noundef` for intrinsic // calls, so we don't *have* to do anything. - let branch: bool = this.machine.rng.get_mut().gen(); + let branch: bool = this.machine.rng.get_mut().random(); this.write_scalar(Scalar::from_bool(branch), dest)?; } @@ -289,7 +289,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let a = this.read_scalar(a)?.to_f32()?; let b = this.read_scalar(b)?.to_f32()?; let c = this.read_scalar(c)?.to_f32()?; - let fuse: bool = this.machine.rng.get_mut().gen(); + let fuse: bool = this.machine.rng.get_mut().random(); let res = if fuse { // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() @@ -304,7 +304,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let a = this.read_scalar(a)?.to_f64()?; let b = this.read_scalar(b)?.to_f64()?; let c = this.read_scalar(c)?.to_f64()?; - let fuse: bool = this.machine.rng.get_mut().gen(); + let fuse: bool = this.machine.rng.get_mut().random(); let res = if fuse { // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index 63a61dcd14878..45e316b190a68 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -304,7 +304,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let c = this.read_scalar(&this.project_index(&c, i)?)?; let dest = this.project_index(&dest, i)?; - let fuse: bool = intrinsic_name == "fma" || this.machine.rng.get_mut().gen(); + let fuse: bool = intrinsic_name == "fma" || this.machine.rng.get_mut().random(); // Works for f32 and f64. // FIXME: using host floats to work around https://github.com/rust-lang/miri/issues/2468. @@ -639,8 +639,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let (right, right_len) = this.project_to_simd(right)?; let (dest, dest_len) = this.project_to_simd(dest)?; - let index = - generic_args[2].expect_const().to_value().valtree.unwrap_branch(); + let index = generic_args[2].expect_const().to_value().valtree.unwrap_branch(); let index_len = index.len(); assert_eq!(left_len, right_len); diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 3ec35763a7d05..5d3204a527f99 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -36,6 +36,7 @@ clippy::needless_question_mark, clippy::needless_lifetimes, clippy::too_long_first_doc_paragraph, + // We don't use translatable diagnostics rustc::diagnostic_outside_of_impl, // We are not implementing queries here so it's fine rustc::potential_query_instability, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 3727b5f4cae4a..4735db48e81f8 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1112,10 +1112,13 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { // Call the lang item. let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap(); let panic = ty::Instance::mono(ecx.tcx.tcx, panic); - ecx.call_function(panic, ExternAbi::Rust, &[], None, StackPopCleanup::Goto { - ret: None, - unwind: mir::UnwindAction::Unreachable, - })?; + ecx.call_function( + panic, + ExternAbi::Rust, + &[], + None, + StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable }, + )?; interp_ok(()) } @@ -1501,7 +1504,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { catch_unwind: None, timing, is_user_relevant: ecx.machine.is_user_relevant(&frame), - salt: ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL, + salt: ecx.machine.rng.borrow_mut().random_range(0..ADDRS_PER_ANON_GLOBAL), data_race: ecx.machine.data_race.as_ref().map(|_| data_race::FrameState::default()), }; @@ -1716,7 +1719,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { if unique { CTFE_ALLOC_SALT } else { - ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL + ecx.machine.rng.borrow_mut().random_range(0..ADDRS_PER_ANON_GLOBAL) } } diff --git a/src/tools/miri/src/math.rs b/src/tools/miri/src/math.rs index ed3d2d55678e2..7117f722fee89 100644 --- a/src/tools/miri/src/math.rs +++ b/src/tools/miri/src/math.rs @@ -1,9 +1,12 @@ use rand::Rng as _; -use rand::distributions::Distribution as _; use rustc_apfloat::Float as _; use rustc_apfloat::ieee::IeeeFloat; -/// Disturbes a floating-point result by a relative error on the order of (-2^scale, 2^scale). +/// Disturbes a floating-point result by a relative error in the range (-2^scale, 2^scale). +/// +/// For a 2^N ULP error, you can use an `err_scale` of `-(F::PRECISION - 1 - N)`. +/// In other words, a 1 ULP (absolute) error is the same as a `2^-(F::PRECISION-1)` relative error. +/// (Subtracting 1 compensates for the integer bit.) pub(crate) fn apply_random_float_error( ecx: &mut crate::MiriInterpCx<'_>, val: F, @@ -11,12 +14,15 @@ pub(crate) fn apply_random_float_error( ) -> F { let rng = ecx.machine.rng.get_mut(); // Generate a random integer in the range [0, 2^PREC). - let dist = rand::distributions::Uniform::new(0, 1 << F::PRECISION); - let err = F::from_u128(dist.sample(rng)) - .value - .scalbn(err_scale.strict_sub(F::PRECISION.try_into().unwrap())); + // (When read as binary, the position of the first `1` determines the exponent, + // and the remaining bits fill the mantissa. `PREC` is one plus the size of the mantissa, + // so this all works out.) + let r = F::from_u128(rng.random_range(0..(1 << F::PRECISION))).value; + // Multiply this with 2^(scale - PREC). The result is between 0 and + // 2^PREC * 2^(scale - PREC) = 2^scale. + let err = r.scalbn(err_scale.strict_sub(F::PRECISION.try_into().unwrap())); // give it a random sign - let err = if rng.gen::() { -err } else { err }; + let err = if rng.random() { -err } else { err }; // multiple the value with (1+err) (val * (F::from_u128(1).value + err).value).value } diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index 43c628d66d590..c588b6fc7f159 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -108,7 +108,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Pick one of the NaNs. let nan = nans.choose(&mut *rand).unwrap(); // Non-deterministically flip the sign. - if rand.gen() { + if rand.random() { // This will properly flip even for NaN. -nan } else { @@ -120,6 +120,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_ref(); // Return one side non-deterministically. let mut rand = this.machine.rng.borrow_mut(); - if rand.gen() { a } else { b } + if rand.random() { a } else { b } } } diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index 0fda13e061600..323b95d5f5f23 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -81,7 +81,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn malloc(&mut self, size: u64, init: AllocInit) -> InterpResult<'tcx, Pointer> { let this = self.eval_context_mut(); let align = this.malloc_align(size); - let ptr = this.allocate_ptr(Size::from_bytes(size), align, MiriMemoryKind::C.into(), init)?; + let ptr = + this.allocate_ptr(Size::from_bytes(size), align, MiriMemoryKind::C.into(), init)?; interp_ok(ptr.into()) } @@ -92,7 +93,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { size: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let memptr = this.deref_pointer(memptr)?; + let memptr = this.deref_pointer_as(memptr, this.machine.layouts.mut_raw_ptr)?; let align = this.read_target_usize(align)?; let size = this.read_target_usize(size)?; @@ -105,7 +106,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(size), Align::from_bytes(align).unwrap(), MiriMemoryKind::C.into(), - AllocInit::Uninit + AllocInit::Uninit, )?; this.write_pointer(ptr, &memptr)?; interp_ok(Scalar::from_i32(0)) @@ -138,7 +139,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(new_size), new_align, MiriMemoryKind::C.into(), - AllocInit::Uninit + AllocInit::Uninit, )?; interp_ok(new_ptr.into()) } @@ -179,7 +180,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(size), Align::from_bytes(align).unwrap(), MiriMemoryKind::C.into(), - AllocInit::Uninit + AllocInit::Uninit, )?; interp_ok(ptr.into()) } diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 1622ef280d25c..137666160d227 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -89,9 +89,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { 1 => { let [_flags, buf] = this.check_shim(abi, Conv::Rust, link_name, args)?; - let buf_place = this.deref_pointer(buf)?; - let ptr_layout = this.layout_of(ptr_ty)?; + let buf_place = this.deref_pointer_as(buf, ptr_layout)?; for (i, ptr) in ptrs.into_iter().enumerate() { let offset = ptr_layout.size.checked_mul(i.try_into().unwrap(), this).unwrap(); diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index f0aebfe169378..20dd3c8db2a3e 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -60,10 +60,10 @@ impl<'tcx> MiriMachine<'tcx> { match ecx.tcx.sess.target.os.as_ref() { "linux" => { - Self::null_ptr_extern_statics(ecx, &[ - "__cxa_thread_atexit_impl", - "__clock_gettime64", - ])?; + Self::null_ptr_extern_statics( + ecx, + &["__cxa_thread_atexit_impl", "__clock_gettime64"], + )?; Self::weak_symbol_extern_statics(ecx, &["getrandom", "statx"])?; } "freebsd" => { diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 1ce0c209de9e2..d84f414af142f 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -509,7 +509,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(size), Align::from_bytes(align).unwrap(), memory_kind.into(), - AllocInit::Uninit + AllocInit::Uninit, )?; ecx.write_pointer(ptr, dest) @@ -538,7 +538,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(size), Align::from_bytes(align).unwrap(), MiriMemoryKind::Rust.into(), - AllocInit::Zero + AllocInit::Zero, )?; this.write_pointer(ptr, dest) }); @@ -599,7 +599,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(new_size), align, MiriMemoryKind::Rust.into(), - AllocInit::Uninit + AllocInit::Uninit, )?; this.write_pointer(new_ptr, dest) }); @@ -861,7 +861,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "lgammaf_r" => { let [x, signp] = this.check_shim(abi, Conv::C, link_name, args)?; let x = this.read_scalar(x)?.to_f32()?; - let signp = this.deref_pointer(signp)?; + let signp = this.deref_pointer_as(signp, this.machine.layouts.i32)?; // Using host floats (but it's fine, these operations do not have guaranteed precision). let (res, sign) = x.to_host().ln_gamma(); @@ -872,7 +872,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "lgamma_r" => { let [x, signp] = this.check_shim(abi, Conv::C, link_name, args)?; let x = this.read_scalar(x)?.to_f64()?; - let signp = this.deref_pointer(signp)?; + let signp = this.deref_pointer_as(signp, this.machine.layouts.i32)?; // Using host floats (but it's fine, these operations do not have guaranteed precision). let (res, sign) = x.to_host().ln_gamma(); diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index 93479540009ea..83f331bb173db 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -247,10 +247,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Call the lang item associated with this message. let fn_item = this.tcx.require_lang_item(msg.panic_function(), None); let instance = ty::Instance::mono(this.tcx.tcx, fn_item); - this.call_function(instance, ExternAbi::Rust, &[], None, StackPopCleanup::Goto { - ret: None, - unwind, - })?; + this.call_function( + instance, + ExternAbi::Rust, + &[], + None, + StackPopCleanup::Goto { ret: None, unwind }, + )?; } } interp_ok(()) diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index d6c77d9c4d9a0..64b3ce6b4e494 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -132,16 +132,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.assert_target_os_is_unix("localtime_r"); this.check_no_isolation("`localtime_r`")?; - let timep = this.deref_pointer(timep)?; + let time_layout = this.libc_ty_layout("time_t"); + let timep = this.deref_pointer_as(timep, time_layout)?; let result = this.deref_pointer_as(result_op, this.libc_ty_layout("tm"))?; // The input "represents the number of seconds elapsed since the Epoch, // 1970-01-01 00:00:00 +0000 (UTC)". - let sec_since_epoch: i64 = this - .read_scalar(&timep)? - .to_int(this.libc_ty_layout("time_t").size)? - .try_into() - .unwrap(); + let sec_since_epoch: i64 = + this.read_scalar(&timep)?.to_int(time_layout.size)?.try_into().unwrap(); let dt_utc: DateTime = DateTime::from_timestamp(sec_since_epoch, 0).expect("Invalid timestamp"); @@ -254,7 +252,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let qpc = i64::try_from(duration.as_nanos()).map_err(|_| { err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported") })?; - this.write_scalar(Scalar::from_i64(qpc), &this.deref_pointer(lpPerformanceCount_op)?)?; + this.write_scalar( + Scalar::from_i64(qpc), + &this.deref_pointer_as(lpPerformanceCount_op, this.machine.layouts.i64)?, + )?; interp_ok(Scalar::from_i32(-1)) // return non-zero on success } diff --git a/src/tools/miri/src/shims/unix/android/thread.rs b/src/tools/miri/src/shims/unix/android/thread.rs index 8d5d4a52b6efe..c7e2c4d507b22 100644 --- a/src/tools/miri/src/shims/unix/android/thread.rs +++ b/src/tools/miri/src/shims/unix/android/thread.rs @@ -3,7 +3,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::{Conv, FnAbi}; -use crate::helpers::check_min_arg_count; +use crate::helpers::check_min_vararg_count; use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult}; use crate::*; @@ -16,18 +16,15 @@ pub fn prctl<'tcx>( args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { - // We do not use `check_shim` here because `prctl` is variadic. The argument - // count is checked bellow. - ecx.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?; + let ([op], varargs) = ecx.check_shim_variadic(abi, Conv::C, link_name, args)?; // FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch. let pr_set_name = 15; let pr_get_name = 16; - let [op] = check_min_arg_count("prctl", args)?; let res = match ecx.read_scalar(op)?.to_i32()? { op if op == pr_set_name => { - let [_, name] = check_min_arg_count("prctl(PR_SET_NAME, ...)", args)?; + let [name] = check_min_vararg_count("prctl(PR_SET_NAME, ...)", varargs)?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; // The Linux kernel silently truncates long names. @@ -38,7 +35,7 @@ pub fn prctl<'tcx>( Scalar::from_u32(0) } op if op == pr_get_name => { - let [_, name] = check_min_arg_count("prctl(PR_GET_NAME, ...)", args)?; + let [name] = check_min_vararg_count("prctl(PR_GET_NAME, ...)", varargs)?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; let len = Scalar::from_target_usize(TASK_COMM_LEN as u64, ecx); diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 0b59490308b44..e7b11e59f8c3e 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -6,7 +6,7 @@ use std::io::ErrorKind; use rustc_abi::Size; -use crate::helpers::check_min_arg_count; +use crate::helpers::check_min_vararg_count; use crate::shims::files::FileDescription; use crate::shims::unix::linux_like::epoll::EpollReadyEvents; use crate::shims::unix::*; @@ -127,11 +127,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { + fn fcntl( + &mut self, + fd_num: &OpTy<'tcx>, + cmd: &OpTy<'tcx>, + varargs: &[OpTy<'tcx>], + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let [fd_num, cmd] = check_min_arg_count("fcntl", args)?; - let fd_num = this.read_scalar(fd_num)?.to_i32()?; let cmd = this.read_scalar(cmd)?.to_i32()?; @@ -163,7 +166,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "fcntl(fd, F_DUPFD_CLOEXEC, ...)" }; - let [_, _, start] = check_min_arg_count(cmd_name, args)?; + let [start] = check_min_vararg_count(cmd_name, varargs)?; let start = this.read_scalar(start)?.to_i32()?; if let Some(fd) = this.machine.fds.get(fd_num) { diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 3353cf2cc59d2..d459ec7cb774c 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -205,10 +205,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "fcntl" => { - // `fcntl` is variadic. The argument count is checked based on the first argument - // in `this.fcntl()`, so we do not use `check_shim` here. - this.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?; - let result = this.fcntl(args)?; + let ([fd_num, cmd], varargs) = + this.check_shim_variadic(abi, Conv::C, link_name, args)?; + let result = this.fcntl(fd_num, cmd, varargs)?; this.write_scalar(result, dest)?; } "dup" => { @@ -236,8 +235,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "open" | "open64" => { // `open` is variadic, the third argument is only present when the second argument // has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set - this.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?; - let result = this.open(args)?; + let ([path_raw, flag], varargs) = + this.check_shim_variadic(abi, Conv::C, link_name, args)?; + let result = this.open(path_raw, flag, varargs)?; this.write_scalar(result, dest)?; } "unlink" => { @@ -354,10 +354,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "pipe2" => { // Currently this function does not exist on all Unixes, e.g. on macOS. - if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "solaris" | "illumos") - { - throw_unsup_format!("`pipe2` is not supported on {}", this.tcx.sess.target.os); - } + this.check_target_os(&["linux", "freebsd", "solaris", "illumos"], link_name)?; let [pipefd, flags] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.pipe2(pipefd, Some(flags))?; this.write_scalar(result, dest)?; @@ -402,12 +399,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "reallocarray" => { // Currently this function does not exist on all Unixes, e.g. on macOS. - if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "android") { - throw_unsup_format!( - "`reallocarray` is not supported on {}", - this.tcx.sess.target.os - ); - } + this.check_target_os(&["linux", "freebsd", "android"], link_name)?; let [ptr, nmemb, size] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let nmemb = this.read_target_usize(nmemb)?; @@ -656,13 +648,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "sched_getaffinity" => { // Currently this function does not exist on all Unixes, e.g. on macOS. - if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "android") { - throw_unsup_format!( - "`sched_getaffinity` is not supported on {}", - this.tcx.sess.target.os - ); - } - + this.check_target_os(&["linux", "freebsd", "android"], link_name)?; let [pid, cpusetsize, mask] = this.check_shim(abi, Conv::C, link_name, args)?; let pid = this.read_scalar(pid)?.to_u32()?; let cpusetsize = this.read_target_usize(cpusetsize)?; @@ -699,13 +685,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "sched_setaffinity" => { // Currently this function does not exist on all Unixes, e.g. on macOS. - if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "android") { - throw_unsup_format!( - "`sched_setaffinity` is not supported on {}", - this.tcx.sess.target.os - ); - } - + this.check_target_os(&["linux", "freebsd", "android"], link_name)?; let [pid, cpusetsize, mask] = this.check_shim(abi, Conv::C, link_name, args)?; let pid = this.read_scalar(pid)?.to_u32()?; let cpusetsize = this.read_target_usize(cpusetsize)?; @@ -761,16 +741,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "getentropy" => { // This function is non-standard but exists with the same signature and behavior on // Linux, macOS, FreeBSD and Solaris/Illumos. - if !matches!( - &*this.tcx.sess.target.os, - "linux" | "macos" | "freebsd" | "illumos" | "solaris" | "android" - ) { - throw_unsup_format!( - "`getentropy` is not supported on {}", - this.tcx.sess.target.os - ); - } - + this.check_target_os( + &["linux", "macos", "freebsd", "illumos", "solaris", "android"], + link_name, + )?; let [buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?; let buf = this.read_pointer(buf)?; let bufsize = this.read_target_usize(bufsize)?; @@ -797,15 +771,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "getrandom" => { // This function is non-standard but exists with the same signature and behavior on // Linux, FreeBSD and Solaris/Illumos. - if !matches!( - &*this.tcx.sess.target.os, - "linux" | "freebsd" | "illumos" | "solaris" | "android" - ) { - throw_unsup_format!( - "`getrandom` is not supported on {}", - this.tcx.sess.target.os - ); - } + this.check_target_os( + &["linux", "freebsd", "illumos", "solaris", "android"], + link_name, + )?; let [ptr, len, flags] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; @@ -817,12 +786,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "arc4random_buf" => { // This function is non-standard but exists with the same signature and // same behavior (eg never fails) on FreeBSD and Solaris/Illumos. - if !matches!(&*this.tcx.sess.target.os, "freebsd" | "illumos" | "solaris") { - throw_unsup_format!( - "`arc4random_buf` is not supported on {}", - this.tcx.sess.target.os - ); - } + this.check_target_os(&["freebsd", "illumos", "solaris"], link_name)?; let [ptr, len] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; @@ -842,15 +806,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // For arm32 they did something custom, but similar enough that the same // `_Unwind_RaiseException` impl in miri should work: // https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst - if !matches!( - &*this.tcx.sess.target.os, - "linux" | "freebsd" | "illumos" | "solaris" | "android" | "macos" - ) { - throw_unsup_format!( - "`_Unwind_RaiseException` is not supported on {}", - this.tcx.sess.target.os - ); - } + this.check_target_os( + &["linux", "freebsd", "illumos", "solaris", "android", "macos"], + link_name, + )?; // This function looks and behaves excatly like miri_start_unwind. let [payload] = this.check_shim(abi, Conv::C, link_name, args)?; this.handle_miri_start_unwind(payload)?; @@ -866,8 +825,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // These shims are enabled only when the caller is in the standard library. "pthread_attr_getguardsize" if this.frame_in_std() => { let [_attr, guard_size] = this.check_shim(abi, Conv::C, link_name, args)?; - let guard_size = this.deref_pointer(guard_size)?; let guard_size_layout = this.libc_ty_layout("size_t"); + let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?; this.write_scalar( Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size, @@ -893,8 +852,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.check_shim(abi, Conv::C, link_name, args)?; let _attr_place = this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?; - let addr_place = this.deref_pointer(addr_place)?; - let size_place = this.deref_pointer(size_place)?; + let addr_place = this.deref_pointer_as(addr_place, this.machine.layouts.usize)?; + let size_place = this.deref_pointer_as(size_place, this.machine.layouts.usize)?; this.write_scalar( Scalar::from_uint(this.machine.stack_addr, this.pointer_size()), @@ -928,7 +887,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let pwd = this.deref_pointer_as(pwd, this.libc_ty_layout("passwd"))?; let buf = this.read_pointer(buf)?; let buflen = this.read_target_usize(buflen)?; - let result = this.deref_pointer(result)?; + let result = this.deref_pointer_as(result, this.machine.layouts.mut_raw_ptr)?; // Must be for "us". if uid != UID { diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 03dbd931329c7..08d06fe5d4c61 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -60,17 +60,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // since freebsd 12 the former form can be expected. "stat" | "stat@FBSD_1.0" => { let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_stat(path, buf)?; + let result = this.macos_fbsd_solarish_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat@FBSD_1.0" => { let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_lstat(path, buf)?; + let result = this.macos_fbsd_solarish_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat@FBSD_1.0" => { let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_fstat(fd, buf)?; + let result = this.macos_fbsd_solarish_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r@FBSD_1.0" => { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index cafce62cfedbe..be2a2a9a8f850 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -13,7 +13,7 @@ use rustc_abi::Size; use rustc_data_structures::fx::FxHashMap; use self::shims::time::system_time_to_duration; -use crate::helpers::check_min_arg_count; +use crate::helpers::check_min_vararg_count; use crate::shims::files::{EvalContextExt as _, FileDescription, FileDescriptionRef}; use crate::shims::os_str::bytes_to_os_str; use crate::shims::unix::fd::{FlockOp, UnixFileDescription}; @@ -273,7 +273,7 @@ impl UnixFileDescription for FileHandle { impl<'tcx> EvalContextExtPrivate<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn macos_fbsd_solaris_write_buf( + fn macos_fbsd_solarish_write_stat_buf( &mut self, metadata: FileMetadata, buf_op: &OpTy<'tcx>, @@ -321,9 +321,9 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { } if matches!(&*this.tcx.sess.target.os, "solaris" | "illumos") { - // FIXME: write st_fstype field once libc is updated. - // https://github.com/rust-lang/libc/pull/4145 - //this.write_int_fields_named(&[("st_fstype", 0)], &buf)?; + let st_fstype = this.project_field_named(&buf, "st_fstype")?; + // This is an array; write 0 into first element so that it encodes the empty string. + this.write_int(0, &this.project_index(&st_fstype, 0)?)?; } interp_ok(0) @@ -452,9 +452,12 @@ fn maybe_sync_file( impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { - let [path_raw, flag] = check_min_arg_count("open", args)?; - + fn open( + &mut self, + path_raw: &OpTy<'tcx>, + flag: &OpTy<'tcx>, + varargs: &[OpTy<'tcx>], + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let path_raw = this.read_pointer(path_raw)?; @@ -507,7 +510,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Get the mode. On macOS, the argument type `mode_t` is actually `u16`, but // C integer promotion rules mean that on the ABI level, it gets passed as `u32` // (see https://github.com/rust-lang/rust/issues/71915). - let [_, _, mode] = check_min_arg_count("open(pathname, O_CREAT, ...)", args)?; + let [mode] = check_min_vararg_count("open(pathname, O_CREAT, ...)", varargs)?; let mode = this.read_scalar(mode)?.to_u32()?; #[cfg(unix)] @@ -668,7 +671,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn macos_fbsd_solaris_stat( + fn macos_fbsd_solarish_stat( &mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, @@ -694,11 +697,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solarish_write_stat_buf(metadata, buf_op)?)) } // `lstat` is used to get symlink metadata. - fn macos_fbsd_solaris_lstat( + fn macos_fbsd_solarish_lstat( &mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, @@ -726,10 +729,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solarish_write_stat_buf(metadata, buf_op)?)) } - fn macos_fbsd_solaris_fstat( + fn macos_fbsd_solarish_fstat( &mut self, fd_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, @@ -756,7 +759,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(metadata) => metadata, Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solarish_write_stat_buf(metadata, buf_op)?)) } fn linux_statx( @@ -1109,7 +1112,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(size), dirent_layout.align.abi, MiriMemoryKind::Runtime.into(), - AllocInit::Uninit + AllocInit::Uninit, )?; let entry: Pointer = entry.into(); @@ -1169,6 +1172,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let dirp = this.read_target_usize(dirp_op)?; + let result_place = this.deref_pointer_as(result_op, this.machine.layouts.mut_raw_ptr)?; // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { @@ -1254,15 +1258,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } _ => unreachable!(), } - - let result_place = this.deref_pointer(result_op)?; this.write_scalar(this.read_scalar(entry_op)?, &result_place)?; Scalar::from_i32(0) } None => { // end of stream: return 0, assign *result=NULL - this.write_null(&this.deref_pointer(result_op)?)?; + this.write_null(&result_place)?; Scalar::from_i32(0) } Some(Err(e)) => { @@ -1548,7 +1550,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { - use rand::seq::SliceRandom; + use rand::seq::IndexedRandom; // POSIX defines the template string. const TEMPFILE_TEMPLATE_STR: &str = "XXXXXX"; diff --git a/src/tools/miri/src/shims/unix/linux/mem.rs b/src/tools/miri/src/shims/unix/linux/mem.rs index 6418d749d3d9d..8e5a3021b1c03 100644 --- a/src/tools/miri/src/shims/unix/linux/mem.rs +++ b/src/tools/miri/src/shims/unix/linux/mem.rs @@ -49,7 +49,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(new_size), align, MiriMemoryKind::Mmap.into(), - AllocInit::Zero + AllocInit::Zero, )?; interp_ok(Scalar::from_pointer(ptr, this)) diff --git a/src/tools/miri/src/shims/unix/linux_like/sync.rs b/src/tools/miri/src/shims/unix/linux_like/sync.rs index 51124fb2a003b..836981133611d 100644 --- a/src/tools/miri/src/shims/unix/linux_like/sync.rs +++ b/src/tools/miri/src/shims/unix/linux_like/sync.rs @@ -1,5 +1,5 @@ use crate::concurrency::sync::FutexRef; -use crate::helpers::check_min_arg_count; +use crate::helpers::check_min_vararg_count; use crate::*; struct LinuxFutex { @@ -10,7 +10,7 @@ struct LinuxFutex { /// `args` is the arguments *including* the syscall number. pub fn futex<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - args: &[OpTy<'tcx>], + varargs: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { // The amount of arguments used depends on the type of futex operation. @@ -21,7 +21,7 @@ pub fn futex<'tcx>( // may or may not be left out from the `syscall()` call. // Therefore we don't use `check_arg_count` here, but only check for the // number of arguments to fall within a range. - let [_, addr, op, val] = check_min_arg_count("`syscall(SYS_futex, ...)`", args)?; + let [addr, op, val] = check_min_vararg_count("`syscall(SYS_futex, ...)`", varargs)?; // The first three arguments (after the syscall number itself) are the same to all futex operations: // (int *addr, int op, int val). @@ -55,14 +55,16 @@ pub fn futex<'tcx>( let wait_bitset = op & !futex_realtime == futex_wait_bitset; let (timeout, bitset) = if wait_bitset { - let [_, _, _, _, timeout, uaddr2, bitset] = - check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT_BITSET, ...)`", args)?; + let [_, _, _, timeout, uaddr2, bitset] = check_min_vararg_count( + "`syscall(SYS_futex, FUTEX_WAIT_BITSET, ...)`", + varargs, + )?; let _timeout = ecx.read_pointer(timeout)?; let _uaddr2 = ecx.read_pointer(uaddr2)?; (timeout, ecx.read_scalar(bitset)?.to_u32()?) } else { - let [_, _, _, _, timeout] = - check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT, ...)`", args)?; + let [_, _, _, timeout] = + check_min_vararg_count("`syscall(SYS_futex, FUTEX_WAIT, ...)`", varargs)?; (timeout, u32::MAX) }; @@ -190,8 +192,10 @@ pub fn futex<'tcx>( let futex_ref = futex_ref.futex.clone(); let bitset = if op == futex_wake_bitset { - let [_, _, _, _, timeout, uaddr2, bitset] = - check_min_arg_count("`syscall(SYS_futex, FUTEX_WAKE_BITSET, ...)`", args)?; + let [_, _, _, timeout, uaddr2, bitset] = check_min_vararg_count( + "`syscall(SYS_futex, FUTEX_WAKE_BITSET, ...)`", + varargs, + )?; let _timeout = ecx.read_pointer(timeout)?; let _uaddr2 = ecx.read_pointer(uaddr2)?; ecx.read_scalar(bitset)?.to_u32()? diff --git a/src/tools/miri/src/shims/unix/linux_like/syscall.rs b/src/tools/miri/src/shims/unix/linux_like/syscall.rs index 5fb262e176f0b..22c6dc975070b 100644 --- a/src/tools/miri/src/shims/unix/linux_like/syscall.rs +++ b/src/tools/miri/src/shims/unix/linux_like/syscall.rs @@ -2,7 +2,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::{Conv, FnAbi}; -use crate::helpers::check_min_arg_count; +use crate::helpers::check_min_vararg_count; use crate::shims::unix::linux_like::eventfd::EvalContextExt as _; use crate::shims::unix::linux_like::sync::futex; use crate::*; @@ -14,9 +14,7 @@ pub fn syscall<'tcx>( args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { - // We do not use `check_shim` here because `syscall` is variadic. The argument - // count is checked bellow. - ecx.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?; + let ([op], varargs) = ecx.check_shim_variadic(abi, Conv::C, link_name, args)?; // The syscall variadic function is legal to call with more arguments than needed, // extra arguments are simply ignored. The important check is that when we use an // argument, we have to also check all arguments *before* it to ensure that they @@ -26,14 +24,13 @@ pub fn syscall<'tcx>( let sys_futex = ecx.eval_libc("SYS_futex").to_target_usize(ecx)?; let sys_eventfd2 = ecx.eval_libc("SYS_eventfd2").to_target_usize(ecx)?; - let [op] = check_min_arg_count("syscall", args)?; match ecx.read_target_usize(op)? { // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` // is called if a `HashMap` is created the regular way (e.g. HashMap). num if num == sys_getrandom => { // Used by getrandom 0.1 // The first argument is the syscall id, so skip over it. - let [_, ptr, len, flags] = check_min_arg_count("syscall(SYS_getrandom, ...)", args)?; + let [ptr, len, flags] = check_min_vararg_count("syscall(SYS_getrandom, ...)", varargs)?; let ptr = ecx.read_pointer(ptr)?; let len = ecx.read_target_usize(len)?; @@ -47,10 +44,10 @@ pub fn syscall<'tcx>( } // `futex` is used by some synchronization primitives. num if num == sys_futex => { - futex(ecx, args, dest)?; + futex(ecx, varargs, dest)?; } num if num == sys_eventfd2 => { - let [_, initval, flags] = check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?; + let [initval, flags] = check_min_vararg_count("syscall(SYS_evetfd2, ...)", varargs)?; let result = ecx.eventfd(initval, flags)?; ecx.write_int(result.to_i32()?, dest)?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 85c963774a159..37fb6c1919f5e 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -3,7 +3,6 @@ use rustc_span::Symbol; use rustc_target::callconv::{Conv, FnAbi}; use super::sync::EvalContextExt as _; -use crate::helpers::check_min_arg_count; use crate::shims::unix::*; use crate::*; @@ -40,17 +39,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "stat" | "stat64" | "stat$INODE64" => { let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_stat(path, buf)?; + let result = this.macos_fbsd_solarish_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" | "lstat$INODE64" => { let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_lstat(path, buf)?; + let result = this.macos_fbsd_solarish_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" | "fstat$INODE64" => { let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_fstat(fd, buf)?; + let result = this.macos_fbsd_solarish_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "opendir$INODE64" => { @@ -69,10 +68,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "ioctl" => { - // `ioctl` is variadic. The argument count is checked based on the first argument - // in `this.ioctl()`, so we do not use `check_shim` here. - this.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?; - let result = this.ioctl(args)?; + let ([fd_num, cmd], varargs) = + this.check_shim_variadic(abi, Conv::C, link_name, args)?; + let result = this.ioctl(fd_num, cmd, varargs)?; this.write_scalar(result, dest)?; } @@ -243,12 +241,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(EmulateItemResult::NeedsReturn) } - fn ioctl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { + fn ioctl( + &mut self, + fd_num: &OpTy<'tcx>, + cmd: &OpTy<'tcx>, + _varargs: &[OpTy<'tcx>], + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let fioclex = this.eval_libc_u64("FIOCLEX"); - let [fd_num, cmd] = check_min_arg_count("ioctl", args)?; let fd_num = this.read_scalar(fd_num)?.to_i32()?; let cmd = this.read_scalar(cmd)?.to_u64()?; diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 330c64f06a3e6..5442d38d52b45 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -30,7 +30,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { 'tcx: 'a, { let this = self.eval_context_mut(); - let lock = this.deref_pointer(lock_ptr)?; + let lock = this.deref_pointer_as(lock_ptr, this.libc_ty_layout("os_unfair_lock_s"))?; this.lazy_sync_get_data( &lock, Size::ZERO, // offset for init tracking diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs index 2d5d3a6471ab9..aefeee6f7a3a3 100644 --- a/src/tools/miri/src/shims/unix/mem.rs +++ b/src/tools/miri/src/shims/unix/mem.rs @@ -116,7 +116,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { align, MiriMemoryKind::Mmap.into(), // mmap guarantees new mappings are zero-init. - AllocInit::Zero + AllocInit::Zero, )?; interp_ok(Scalar::from_pointer(ptr, this)) diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs index f94783a390722..21d4f41f48529 100644 --- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs @@ -87,17 +87,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // File related shims "stat" | "stat64" => { let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_stat(path, buf)?; + let result = this.macos_fbsd_solarish_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" => { let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_lstat(path, buf)?; + let result = this.macos_fbsd_solarish_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" => { let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.macos_fbsd_solaris_fstat(fd, buf)?; + let result = this.macos_fbsd_solarish_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir" => { @@ -163,7 +163,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("pset_info is only supported with list==NULL"); } - let cpus = this.deref_pointer(cpus)?; + let cpus = this.deref_pointer_as(cpus, this.machine.layouts.u32)?; this.write_scalar(Scalar::from_u32(this.machine.num_cpus), &cpus)?; this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 5b0a9398b4b6a..9f1fabfbf6494 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -170,7 +170,7 @@ fn mutex_create<'tcx>( mutex_ptr: &OpTy<'tcx>, kind: MutexKind, ) -> InterpResult<'tcx, PthreadMutex> { - let mutex = ecx.deref_pointer(mutex_ptr)?; + let mutex = ecx.deref_pointer_as(mutex_ptr, ecx.libc_ty_layout("pthread_mutex_t"))?; let id = ecx.machine.sync.mutex_create(); let data = PthreadMutex { mutex_ref: id, kind }; ecx.lazy_sync_init(&mutex, mutex_init_offset(ecx)?, data.clone())?; @@ -186,7 +186,7 @@ fn mutex_get_data<'tcx, 'a>( where 'tcx: 'a, { - let mutex = ecx.deref_pointer(mutex_ptr)?; + let mutex = ecx.deref_pointer_as(mutex_ptr, ecx.libc_ty_layout("pthread_mutex_t"))?; ecx.lazy_sync_get_data( &mutex, mutex_init_offset(ecx)?, @@ -265,7 +265,7 @@ fn rwlock_get_data<'tcx, 'a>( where 'tcx: 'a, { - let rwlock = ecx.deref_pointer(rwlock_ptr)?; + let rwlock = ecx.deref_pointer_as(rwlock_ptr, ecx.libc_ty_layout("pthread_rwlock_t"))?; ecx.lazy_sync_get_data( &rwlock, rwlock_init_offset(ecx)?, @@ -383,7 +383,7 @@ fn cond_create<'tcx>( cond_ptr: &OpTy<'tcx>, clock: ClockId, ) -> InterpResult<'tcx, PthreadCondvar> { - let cond = ecx.deref_pointer(cond_ptr)?; + let cond = ecx.deref_pointer_as(cond_ptr, ecx.libc_ty_layout("pthread_cond_t"))?; let id = ecx.machine.sync.condvar_create(); let data = PthreadCondvar { id, clock }; ecx.lazy_sync_init(&cond, cond_init_offset(ecx)?, data)?; @@ -397,7 +397,7 @@ fn cond_get_data<'tcx, 'a>( where 'tcx: 'a, { - let cond = ecx.deref_pointer(cond_ptr)?; + let cond = ecx.deref_pointer_as(cond_ptr, ecx.libc_ty_layout("pthread_cond_t"))?; ecx.lazy_sync_get_data( &cond, cond_init_offset(ecx)?, @@ -760,7 +760,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let clock_id = condattr_get_clock_id(this, attr_op)?; - this.write_scalar(Scalar::from_i32(clock_id), &this.deref_pointer(clk_id_op)?)?; + this.write_scalar( + Scalar::from_i32(clock_id), + &this.deref_pointer_as(clk_id_op, this.libc_ty_layout("clockid_t"))?, + )?; interp_ok(()) } diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index 08515b815a900..4396ff4b1ac35 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -362,7 +362,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let domain = this.read_scalar(domain)?.to_i32()?; let mut flags = this.read_scalar(type_)?.to_i32()?; let protocol = this.read_scalar(protocol)?.to_i32()?; - let sv = this.deref_pointer(sv)?; + // This is really a pointer to `[i32; 2]` but we use a ptr-to-first-element representation. + let sv = this.deref_pointer_as(sv, this.machine.layouts.i32)?; let mut is_sock_nonblock = false; diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs index 72c1fb58023a8..1b2ccd99ef9f4 100644 --- a/src/tools/miri/src/shims/windows/env.rs +++ b/src/tools/miri/src/shims/windows/env.rs @@ -218,7 +218,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let token = this.read_target_isize(token)?; let buf = this.read_pointer(buf)?; - let size = this.deref_pointer(size)?; + let size = this.deref_pointer_as(size, this.machine.layouts.u32)?; if token != -4 { throw_unsup_format!( diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 4462d025beada..fae6170a9e72c 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -266,7 +266,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(size), Align::from_bytes(align).unwrap(), MiriMemoryKind::WinHeap.into(), - init + init, )?; this.write_pointer(ptr, dest)?; } @@ -299,7 +299,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Size::from_bytes(size), Align::from_bytes(align).unwrap(), MiriMemoryKind::WinHeap.into(), - AllocInit::Uninit + AllocInit::Uninit, )?; this.write_pointer(new_ptr, dest)?; } @@ -335,7 +335,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Initialize with `0`. this.write_bytes_ptr( system_info.ptr(), - iter::repeat(0u8).take(system_info.layout.size.bytes_usize()), + iter::repeat_n(0u8, system_info.layout.size.bytes_usize()), )?; // Set selected fields. this.write_int_fields_named( @@ -523,7 +523,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [handle, name_ptr] = this.check_shim(abi, sys_conv, link_name, args)?; let handle = this.read_scalar(handle)?; - let name_ptr = this.deref_pointer(name_ptr)?; // the pointer where we should store the ptr to the name + let name_ptr = this.deref_pointer_as(name_ptr, this.machine.layouts.mut_raw_ptr)?; // the pointer where we should store the ptr to the name let thread = match Handle::try_from_scalar(handle, this)? { Ok(Handle::Thread(thread)) => Ok(thread), @@ -725,7 +725,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "GetConsoleMode" if this.frame_in_std() => { let [console, mode] = this.check_shim(abi, sys_conv, link_name, args)?; this.read_target_isize(console)?; - this.deref_pointer(mode)?; + this.deref_pointer_as(mode, this.machine.layouts.u32)?; // Indicate an error. this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 4001201bf678a..808a7786eb9f3 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -29,7 +29,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { { let this = self.eval_context_mut(); - let init_once = this.deref_pointer(init_once_ptr)?; + let init_once = + this.deref_pointer_as(init_once_ptr, this.windows_ty_layout("INIT_ONCE"))?; let init_offset = Size::ZERO; this.lazy_sync_get_data( @@ -85,7 +86,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let id = this.init_once_get_data(init_once_op)?.id; let flags = this.read_scalar(flags_op)?.to_u32()?; - let pending_place = this.deref_pointer(pending_op)?; + // PBOOL is int* + let pending_place = this.deref_pointer_as(pending_op, this.machine.layouts.i32)?; let context = this.read_pointer(context_op)?; if flags != 0 { diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs index efc1c2286bcbc..5db554044227c 100644 --- a/src/tools/miri/src/shims/windows/thread.rs +++ b/src/tools/miri/src/shims/windows/thread.rs @@ -29,7 +29,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let thread = if this.ptr_is_null(this.read_pointer(thread_op)?)? { None } else { - let thread_info_place = this.deref_pointer(thread_op)?; + let thread_info_place = this.deref_pointer_as(thread_op, this.machine.layouts.u32)?; Some(thread_info_place) }; diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index 0a5e9f62dd9fb..af92f9d0dec49 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -105,6 +105,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", +] + [[package]] name = "gimli" version = "0.29.0" @@ -178,6 +190,7 @@ dependencies = [ "cfg-if", "getrandom 0.1.16", "getrandom 0.2.15", + "getrandom 0.3.1", "libc", "num_cpus", "page_size", @@ -359,6 +372,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -507,3 +529,12 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index e7eff46afca52..78dddaf11dff5 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -8,13 +8,14 @@ version = "0.1.0" edition = "2021" [dependencies] -# all dependencies (and their transitive ones) listed here can be used in `tests/`. +# all dependencies (and their transitive ones) listed here can be used in `tests/*-dep`. libc = "0.2" num_cpus = "1.10.1" cfg-if = "1" getrandom_01 = { package = "getrandom", version = "0.1" } getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] } +getrandom_03 = { package = "getrandom", version = "0.3" } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies] tempfile = "3" diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs index 4b6f344a78e28..457f32e55446e 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs @@ -8,5 +8,5 @@ fn main() { fn test_file_open_missing_needed_mode() { let name = b"missing_arg.txt\0"; let name_ptr = name.as_ptr().cast::(); - let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: incorrect number of arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 + let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: not enough variadic arguments } diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr index ca9e3c6c4be40..f48b75460d4f9 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: incorrect number of arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 +error: Undefined Behavior: not enough variadic arguments for `open(pathname, O_CREAT, ...)`: got 0, expected at least 1 --> tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs:LL:CC | -LL | ... { libc::open(name_ptr, libc::O_CREAT) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 +LL | let _fd = unsafe { libc::open(name_ptr, libc::O_CREAT) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not enough variadic arguments for `open(pathname, O_CREAT, ...)`: got 0, expected at least 1 | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs new file mode 100644 index 0000000000000..b920e6795f90d --- /dev/null +++ b/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs @@ -0,0 +1,17 @@ +//@ignore-target: windows # File handling is not implemented yet +//@compile-flags: -Zmiri-disable-isolation +use std::ffi::{CString, OsStr, c_char, c_int}; +use std::os::unix::ffi::OsStrExt; + +// Declare a variadic function as non-variadic. +extern "C" { + fn open(path: *const c_char, oflag: c_int) -> c_int; +} + +fn main() { + let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let _fd = unsafe { + open(c_path.as_ptr(), /* value does not matter */ 0) + //~^ ERROR: calling a variadic function with a non-variadic caller-side signature + }; +} diff --git a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr new file mode 100644 index 0000000000000..43813af9a3c61 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: calling a variadic function with a non-variadic caller-side signature + --> tests/fail/shims/non_vararg_signature_mismatch.rs:LL:CC + | +LL | open(c_path.as_ptr(), /* value does not matter */ 0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a variadic function with a non-variadic caller-side signature + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail/shims/non_vararg_signature_mismatch.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs new file mode 100644 index 0000000000000..e9cb69418d22f --- /dev/null +++ b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs @@ -0,0 +1,16 @@ +//@ignore-target: windows # File handling is not implemented yet +//@compile-flags: -Zmiri-disable-isolation +use std::ffi::{CString, OsStr, c_char, c_int}; +use std::os::unix::ffi::OsStrExt; + +extern "C" { + fn open(path: *const c_char, ...) -> c_int; +} + +fn main() { + let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let _fd = unsafe { + open(c_path.as_ptr(), /* value does not matter */ 0) + //~^ ERROR: incorrect number of fixed arguments for variadic function + }; +} diff --git a/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.stderr b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.stderr new file mode 100644 index 0000000000000..12e464813cfff --- /dev/null +++ b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: incorrect number of fixed arguments for variadic function `open`: got 1, expected 2 + --> tests/fail/shims/wrong_fixed_arg_count.rs:LL:CC + | +LL | open(c_path.as_ptr(), /* value does not matter */ 0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of fixed arguments for variadic function `open`: got 1, expected 2 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail/shims/wrong_fixed_arg_count.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass-dep/getrandom.rs b/src/tools/miri/tests/pass-dep/getrandom.rs index a5bc5ec7079be..d359730e7f971 100644 --- a/src/tools/miri/tests/pass-dep/getrandom.rs +++ b/src/tools/miri/tests/pass-dep/getrandom.rs @@ -3,7 +3,7 @@ //@revisions: isolation no_isolation //@[no_isolation]compile-flags: -Zmiri-disable-isolation -/// Test direct calls of getrandom 0.1 and 0.2. +/// Test direct calls of getrandom 0.1, 0.2 and 0.3. fn main() { let mut data = vec![0; 16]; @@ -13,4 +13,6 @@ fn main() { getrandom_01::getrandom(&mut data).unwrap(); getrandom_02::getrandom(&mut data).unwrap(); + + getrandom_03::fill(&mut data).unwrap(); } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs index 23e2122ee50fa..dc3ab2828faa2 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs @@ -230,10 +230,10 @@ fn test_two_same_fd_in_same_epoll_instance() { //Two notification should be received. let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = 5 as u64; - check_epoll_wait::<8>(epfd, &[ - (expected_event, expected_value), - (expected_event, expected_value), - ]); + check_epoll_wait::<8>( + epfd, + &[(expected_event, expected_value), (expected_event, expected_value)], + ); } fn test_epoll_eventfd() { @@ -290,10 +290,10 @@ fn test_epoll_socketpair_both_sides() { let expected_value0 = fds[0] as u64; let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); let expected_value1 = fds[1] as u64; - check_epoll_wait::<8>(epfd, &[ - (expected_event0, expected_value0), - (expected_event1, expected_value1), - ]); + check_epoll_wait::<8>( + epfd, + &[(expected_event0, expected_value0), (expected_event1, expected_value1)], + ); // Read from fds[0]. let mut buf: [u8; 5] = [0; 5]; @@ -453,10 +453,10 @@ fn test_socketpair_read() { let expected_value0 = fds[0] as u64; let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); let expected_value1 = fds[1] as u64; - check_epoll_wait::<8>(epfd, &[ - (expected_event0, expected_value0), - (expected_event1, expected_value1), - ]); + check_epoll_wait::<8>( + epfd, + &[(expected_event0, expected_value0), (expected_event1, expected_value1)], + ); // Read 3 bytes from fds[0]. let mut buf: [u8; 3] = [0; 3]; diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 9b9542b88a962..3bc953c3a5fbf 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -13,7 +13,7 @@ use ui_test::custom_flags::edition::Edition; use ui_test::dependencies::DependencyBuilder; use ui_test::per_test_config::TestConfig; use ui_test::spanned::Spanned; -use ui_test::{CommandBuilder, Config, Format, Match, OutputConflictHandling, status_emitter}; +use ui_test::{CommandBuilder, Config, Format, Match, ignore_output_conflict, status_emitter}; #[derive(Copy, Clone, Debug)] enum Mode { @@ -82,9 +82,18 @@ fn build_native_lib() -> PathBuf { native_lib_path } +struct WithDependencies { + bless: bool, +} + /// Does *not* set any args or env vars, since it is shared between the test runner and /// run_dep_mode. -fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> Config { +fn miri_config( + target: &str, + path: &str, + mode: Mode, + with_dependencies: Option, +) -> Config { // Miri is rustc-like, so we create a default builder for rustc and modify it let mut program = CommandBuilder::rustc(); program.program = miri_path(); @@ -119,22 +128,26 @@ fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> // keep in sync with `./miri run` config.comment_defaults.base().add_custom("edition", Edition("2021".into())); - if with_dependencies { - config.comment_defaults.base().set_custom("dependencies", DependencyBuilder { - program: CommandBuilder { - // Set the `cargo-miri` binary, which we expect to be in the same folder as the `miri` binary. - // (It's a separate crate, so we don't get an env var from cargo.) - program: miri_path() - .with_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)), - // There is no `cargo miri build` so we just use `cargo miri run`. - args: ["miri", "run"].into_iter().map(Into::into).collect(), - // Reset `RUSTFLAGS` to work around . - envs: vec![("RUSTFLAGS".into(), None)], - ..CommandBuilder::cargo() + if let Some(WithDependencies { bless }) = with_dependencies { + config.comment_defaults.base().set_custom( + "dependencies", + DependencyBuilder { + program: CommandBuilder { + // Set the `cargo-miri` binary, which we expect to be in the same folder as the `miri` binary. + // (It's a separate crate, so we don't get an env var from cargo.) + program: miri_path() + .with_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)), + // There is no `cargo miri build` so we just use `cargo miri run`. + args: ["miri", "run"].into_iter().map(Into::into).collect(), + // Reset `RUSTFLAGS` to work around . + envs: vec![("RUSTFLAGS".into(), None)], + ..CommandBuilder::cargo() + }, + crate_manifest_path: Path::new("test_dependencies").join("Cargo.toml"), + build_std: None, + bless_lockfile: bless, }, - crate_manifest_path: Path::new("test_dependencies").join("Cargo.toml"), - build_std: None, - }); + ); } config } @@ -146,7 +159,20 @@ fn run_tests( with_dependencies: bool, tmpdir: &Path, ) -> Result<()> { + // Handle command-line arguments. + let mut args = ui_test::Args::test()?; + args.bless |= env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); + + let with_dependencies = with_dependencies.then_some(WithDependencies { bless: args.bless }); + let mut config = miri_config(target, path, mode, with_dependencies); + config.with_args(&args); + config.bless_command = Some("./miri test --bless".into()); + + if env::var_os("MIRI_SKIP_UI_CHECKS").is_some() { + assert!(!args.bless, "cannot use RUSTC_BLESS and MIRI_SKIP_UI_CHECKS at the same time"); + config.output_conflict_handling = ignore_output_conflict; + } // Add a test env var to do environment communication tests. config.program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into()))); @@ -182,16 +208,6 @@ fn run_tests( config.program.args.push(flag); } - // Handle command-line arguments. - let mut args = ui_test::Args::test()?; - args.bless |= env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); - config.with_args(&args); - config.bless_command = Some("./miri test --bless".into()); - - if env::var_os("MIRI_SKIP_UI_CHECKS").is_some() { - assert!(!args.bless, "cannot use RUSTC_BLESS and MIRI_SKIP_UI_CHECKS at the same time"); - config.output_conflict_handling = OutputConflictHandling::Ignore; - } eprintln!(" Compiler: {}", config.program.display()); ui_test::run_tests_generic( // Only run one test suite. In the future we can add all test suites to one `Vec` and run @@ -327,7 +343,8 @@ fn main() -> Result<()> { } fn run_dep_mode(target: String, args: impl Iterator) -> Result<()> { - let mut config = miri_config(&target, "", Mode::RunDep, /* with dependencies */ true); + let mut config = + miri_config(&target, "", Mode::RunDep, Some(WithDependencies { bless: false })); config.comment_defaults.base().custom.remove("edition"); // `./miri` adds an `--edition` in `args`, so don't set it twice config.fill_host_and_target()?; config.program.args = args.collect();