about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-26 10:29:03 +0000
committerbors <bors@rust-lang.org>2023-12-26 10:29:03 +0000
commitea7ef7b6c224226a4bd9f9796de39d57b527f7f9 (patch)
treea3cd960665d554495f63148fab3795f4909d9cf8
parenta815c3b69c527c268015f017a88d88331f150a02 (diff)
parent4658d3816c8b103f0333aef93d2f36f0bf638338 (diff)
downloadrust-ea7ef7b6c224226a4bd9f9796de39d57b527f7f9.tar.gz
rust-ea7ef7b6c224226a4bd9f9796de39d57b527f7f9.zip
Auto merge of #119315 - RalfJung:miri, r=RalfJung
Miri subtree update

r? `@ghost`
-rw-r--r--src/tools/miri/miri-script/src/commands.rs17
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs48
-rw-r--r--src/tools/miri/src/shims/unix/linux/mem.rs7
-rw-r--r--src/tools/miri/src/shims/unix/mem.rs45
-rw-r--r--src/tools/miri/tests/compiletest.rs2
-rw-r--r--src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr17
-rw-r--r--src/tools/miri/tests/fail-dep/shims/munmap.rs22
-rw-r--r--src/tools/miri/tests/fail-dep/shims/munmap.stderr39
-rw-r--r--src/tools/miri/tests/fail-dep/shims/munmap_partial.rs8
-rw-r--r--src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr24
-rw-r--r--src/tools/miri/tests/pass-dep/shims/mmap.rs5
-rw-r--r--src/tools/miri/tests/pass/portable-simd.rs69
13 files changed, 155 insertions, 150 deletions
diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs
index e4789c696b3..aa43aa15485 100644
--- a/src/tools/miri/miri-script/src/commands.rs
+++ b/src/tools/miri/miri-script/src/commands.rs
@@ -344,7 +344,7 @@ impl Command {
         println!(
             // Open PR with `subtree update` title to silence the `no-merges` triagebot check
             // See https://github.com/rust-lang/rust/pull/114157
-            "    https://github.com/rust-lang/rust/compare/{github_user}:{branch}?quick_pull=1&title=Miri+subtree+update"
+            "    https://github.com/rust-lang/rust/compare/{github_user}:{branch}?quick_pull=1&title=Miri+subtree+update&body=r?+@ghost"
         );
 
         drop(josh);
@@ -478,7 +478,11 @@ impl Command {
         // Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
         // that we set the MIRI_SYSROOT up the right way.
         use itertools::Itertools;
-        let target = flags.iter().tuple_windows().find(|(first, _)| first == &"--target");
+        let target = flags
+            .iter()
+            .take_while(|arg| *arg != "--")
+            .tuple_windows()
+            .find(|(first, _)| *first == "--target");
         if let Some((_, target)) = target {
             // Found it!
             e.sh.set_var("MIRI_TEST_TARGET", target);
@@ -487,6 +491,10 @@ impl Command {
             let miriflags = e.sh.var("MIRIFLAGS").unwrap_or_default();
             e.sh.set_var("MIRIFLAGS", format!("{miriflags} --target {target}"));
         }
+        // Scan for "--edition" (we'll set one ourselves if that flag is not present).
+        let have_edition =
+            flags.iter().take_while(|arg| *arg != "--").any(|arg| *arg == "--edition");
+
         // Prepare a sysroot.
         e.build_miri_sysroot(/* quiet */ true)?;
 
@@ -496,15 +504,16 @@ impl Command {
         let miri_flags = flagsplit(&miri_flags);
         let toolchain = &e.toolchain;
         let extra_flags = &e.cargo_extra_flags;
+        let edition_flags = (!have_edition).then_some("--edition=2021"); // keep in sync with `compiletest.rs`.`
         if dep {
             cmd!(
                 e.sh,
-                "cargo +{toolchain} --quiet test --test compiletest {extra_flags...} --manifest-path {miri_manifest} -- --miri-run-dep-mode {miri_flags...} {flags...}"
+                "cargo +{toolchain} --quiet test --test compiletest {extra_flags...} --manifest-path {miri_manifest} -- --miri-run-dep-mode {miri_flags...} {edition_flags...} {flags...}"
             ).quiet().run()?;
         } else {
             cmd!(
                 e.sh,
-                "cargo +{toolchain} --quiet run {extra_flags...} --manifest-path {miri_manifest} -- {miri_flags...} {flags...}"
+                "cargo +{toolchain} --quiet run {extra_flags...} --manifest-path {miri_manifest} -- {miri_flags...} {edition_flags...} {flags...}"
             ).quiet().run()?;
         }
         Ok(())
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index e82b7f84154..5298ff36f21 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-604f185fae9a4b0edf7e28f616a0f53880f8f074
+2271c26e4a8e062bb00d709d0ccb5846e0c341b9
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index e17c06be9b8..2c8493d8aad 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -656,6 +656,54 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     }
                 }
             }
+            "masked_load" => {
+                let [mask, ptr, default] = check_arg_count(args)?;
+                let (mask, mask_len) = this.operand_to_simd(mask)?;
+                let ptr = this.read_pointer(ptr)?;
+                let (default, default_len) = this.operand_to_simd(default)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(dest_len, mask_len);
+                assert_eq!(dest_len, default_len);
+
+                for i in 0..dest_len {
+                    let mask = this.read_immediate(&this.project_index(&mask, i)?)?;
+                    let default = this.read_immediate(&this.project_index(&default, i)?)?;
+                    let dest = this.project_index(&dest, i)?;
+
+                    let val = if simd_element_to_bool(mask)? {
+                        // Size * u64 is implemented as always checked
+                        #[allow(clippy::arithmetic_side_effects)]
+                        let ptr = ptr.wrapping_offset(dest.layout.size * i, this);
+                        let place = this.ptr_to_mplace(ptr, dest.layout);
+                        this.read_immediate(&place)?
+                    } else {
+                        default
+                    };
+                    this.write_immediate(*val, &dest)?;
+                }
+            }
+            "masked_store" => {
+                let [mask, ptr, vals] = check_arg_count(args)?;
+                let (mask, mask_len) = this.operand_to_simd(mask)?;
+                let ptr = this.read_pointer(ptr)?;
+                let (vals, vals_len) = this.operand_to_simd(vals)?;
+
+                assert_eq!(mask_len, vals_len);
+
+                for i in 0..vals_len {
+                    let mask = this.read_immediate(&this.project_index(&mask, i)?)?;
+                    let val = this.read_immediate(&this.project_index(&vals, i)?)?;
+
+                    if simd_element_to_bool(mask)? {
+                        // Size * u64 is implemented as always checked
+                        #[allow(clippy::arithmetic_side_effects)]
+                        let ptr = ptr.wrapping_offset(val.layout.size * i, this);
+                        let place = this.ptr_to_mplace(ptr, val.layout);
+                        this.write_immediate(*val, &place)?
+                    };
+                }
+            }
 
             name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"),
         }
diff --git a/src/tools/miri/src/shims/unix/linux/mem.rs b/src/tools/miri/src/shims/unix/linux/mem.rs
index d1b4416cb1d..ec2922d0275 100644
--- a/src/tools/miri/src/shims/unix/linux/mem.rs
+++ b/src/tools/miri/src/shims/unix/linux/mem.rs
@@ -15,14 +15,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
-        let old_address = this.read_target_usize(old_address)?;
+        let old_address = this.read_pointer(old_address)?;
         let old_size = this.read_target_usize(old_size)?;
         let new_size = this.read_target_usize(new_size)?;
         let flags = this.read_scalar(flags)?.to_i32()?;
 
         // old_address must be a multiple of the page size
         #[allow(clippy::arithmetic_side_effects)] // PAGE_SIZE is nonzero
-        if old_address % this.machine.page_size != 0 || new_size == 0 {
+        if old_address.addr().bytes() % this.machine.page_size != 0 || new_size == 0 {
             this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
             return Ok(this.eval_libc("MAP_FAILED"));
         }
@@ -41,7 +41,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             return Ok(this.eval_libc("MAP_FAILED"));
         }
 
-        let old_address = Machine::ptr_from_addr_cast(this, old_address)?;
         let align = this.machine.page_align();
         let ptr = this.reallocate_ptr(
             old_address,
@@ -59,8 +58,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             )
             .unwrap();
         }
-        // Memory mappings are always exposed
-        Machine::expose_ptr(this, ptr)?;
 
         Ok(Scalar::from_pointer(ptr, this))
     }
diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs
index 5b84f047f49..5aa514715bc 100644
--- a/src/tools/miri/src/shims/unix/mem.rs
+++ b/src/tools/miri/src/shims/unix/mem.rs
@@ -6,6 +6,13 @@
 //! mmap/munmap behave a lot like alloc/dealloc, and for simple use they are exactly
 //! equivalent. That is the only part we support: no MAP_FIXED or MAP_SHARED or anything
 //! else that goes beyond a basic allocation API.
+//!
+//! Note that in addition to only supporting malloc-like calls to mmap, we only support free-like
+//! calls to munmap, but for a very different reason. In principle, according to the man pages, it
+//! is possible to unmap arbitrary regions of address space. But in a high-level language like Rust
+//! this amounts to partial deallocation, which LLVM does not support. So any attempt to call our
+//! munmap shim which would partily unmap a region of address space previously mapped by mmap will
+//! report UB.
 
 use crate::{helpers::round_to_next_multiple_of, *};
 use rustc_target::abi::Size;
@@ -100,8 +107,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             std::iter::repeat(0u8).take(usize::try_from(map_length).unwrap()),
         )
         .unwrap();
-        // Memory mappings don't use provenance, and are always exposed.
-        Machine::expose_ptr(this, ptr)?;
 
         Ok(Scalar::from_pointer(ptr, this))
     }
@@ -113,43 +118,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
-        let addr = this.read_target_usize(addr)?;
+        let addr = this.read_pointer(addr)?;
         let length = this.read_target_usize(length)?;
 
-        // addr must be a multiple of the page size
+        // addr must be a multiple of the page size, but apart from that munmap is just implemented
+        // as a dealloc.
         #[allow(clippy::arithmetic_side_effects)] // PAGE_SIZE is nonzero
-        if addr % this.machine.page_size != 0 {
+        if addr.addr().bytes() % this.machine.page_size != 0 {
             this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
             return Ok(Scalar::from_i32(-1));
         }
 
-        let length = round_to_next_multiple_of(length, this.machine.page_size);
-
-        let ptr = Machine::ptr_from_addr_cast(this, addr)?;
-
-        let Ok(ptr) = ptr.into_pointer_or_addr() else {
-            throw_unsup_format!("Miri only supports munmap on memory allocated directly by mmap");
-        };
-        let Some((alloc_id, offset, _prov)) = Machine::ptr_get_alloc(this, ptr) else {
-            throw_unsup_format!("Miri only supports munmap on memory allocated directly by mmap");
-        };
-
-        // Elsewhere in this function we are careful to check what we can and throw an unsupported
-        // error instead of Undefined Behavior when use of this function falls outside of the
-        // narrow scope we support. We deliberately do not check the MemoryKind of this allocation,
-        // because we want to report UB on attempting to unmap memory that Rust "understands", such
-        // the stack, heap, or statics.
-        let (_kind, alloc) = this.memory.alloc_map().get(alloc_id).unwrap();
-        if offset != Size::ZERO || alloc.len() as u64 != length {
-            throw_unsup_format!(
-                "Miri only supports munmap calls that exactly unmap a region previously returned by mmap"
-            );
-        }
-
-        let len = Size::from_bytes(alloc.len() as u64);
+        let length = Size::from_bytes(round_to_next_multiple_of(length, this.machine.page_size));
         this.deallocate_ptr(
-            ptr.into(),
-            Some((len, this.machine.page_align())),
+            addr,
+            Some((length, this.machine.page_align())),
             MemoryKind::Machine(MiriMemoryKind::Mmap),
         )?;
 
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index 91df4985c0f..3394c4a49f8 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -91,7 +91,7 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
         mode,
         program,
         out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("ui"),
-        edition: Some("2021".into()),
+        edition: Some("2021".into()), // keep in sync with `./miri run`
         threads: std::env::var("MIRI_TEST_THREADS")
             .ok()
             .map(|threads| NonZeroUsize::new(threads.parse().unwrap()).unwrap()),
diff --git a/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr b/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr
index 21b4baa5009..49f2b84baa8 100644
--- a/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr
+++ b/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr
@@ -1,18 +1,3 @@
-warning: integer-to-pointer cast
-  --> $DIR/mmap_use_after_munmap.rs:LL:CC
-   |
-LL |         libc::munmap(ptr, 4096);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
-   |
-   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::from_exposed_addr`,
-   = help: which means that Miri might miss pointer bugs in this program.
-   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html for more details on that operation.
-   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
-   = help: You can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `from_exposed_addr` semantics.
-   = help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
-   = note: BACKTRACE:
-   = note: inside `main` at $DIR/mmap_use_after_munmap.rs:LL:CC
-
 error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
   --> $DIR/mmap_use_after_munmap.rs:LL:CC
    |
@@ -43,5 +28,5 @@ LL |         libc::munmap(ptr, 4096);
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/src/tools/miri/tests/fail-dep/shims/munmap.rs b/src/tools/miri/tests/fail-dep/shims/munmap.rs
deleted file mode 100644
index 453437a06cf..00000000000
--- a/src/tools/miri/tests/fail-dep/shims/munmap.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@compile-flags: -Zmiri-disable-isolation
-//@ignore-target-windows: No libc on Windows
-
-#![feature(rustc_private)]
-#![feature(strict_provenance)]
-
-use std::ptr;
-
-fn main() {
-    // Linux specifies that it is not an error if the specified range does not contain any pages.
-    // But we simply do not support such calls. This test checks that we report this as
-    // unsupported, not Undefined Behavior.
-    let res = unsafe {
-        libc::munmap(
-            //~^ ERROR: unsupported operation
-            // Some high address we surely have not allocated anything at
-            ptr::invalid_mut(1 << 30),
-            4096,
-        )
-    };
-    assert_eq!(res, 0);
-}
diff --git a/src/tools/miri/tests/fail-dep/shims/munmap.stderr b/src/tools/miri/tests/fail-dep/shims/munmap.stderr
deleted file mode 100644
index f17473677f6..00000000000
--- a/src/tools/miri/tests/fail-dep/shims/munmap.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-warning: integer-to-pointer cast
-  --> $DIR/munmap.rs:LL:CC
-   |
-LL | /         libc::munmap(
-LL | |
-LL | |             // Some high address we surely have not allocated anything at
-LL | |             ptr::invalid_mut(1 << 30),
-LL | |             4096,
-LL | |         )
-   | |_________^ integer-to-pointer cast
-   |
-   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::from_exposed_addr`,
-   = help: which means that Miri might miss pointer bugs in this program.
-   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html for more details on that operation.
-   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
-   = help: You can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `from_exposed_addr` semantics.
-   = help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
-   = note: BACKTRACE:
-   = note: inside `main` at $DIR/munmap.rs:LL:CC
-
-error: unsupported operation: Miri only supports munmap on memory allocated directly by mmap
-  --> $DIR/munmap.rs:LL:CC
-   |
-LL | /         libc::munmap(
-LL | |
-LL | |             // Some high address we surely have not allocated anything at
-LL | |             ptr::invalid_mut(1 << 30),
-LL | |             4096,
-LL | |         )
-   | |_________^ Miri only supports munmap on memory allocated directly by mmap
-   |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
-   = note: BACKTRACE:
-   = note: inside `main` at $DIR/munmap.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; 1 warning emitted
-
diff --git a/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs b/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs
index 938850ee286..1d6e4796d0a 100644
--- a/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs
+++ b/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs
@@ -1,6 +1,8 @@
-//! Our mmap/munmap support is a thin wrapper over Interpcx::allocate_ptr. Since the underlying
-//! layer has much more UB than munmap does, we need to be sure we throw an unsupported error here.
+//! The man pages for mmap/munmap suggest that it is possible to partly unmap a previously-mapped
+//! region of addres space, but to LLVM that would be partial deallocation, which LLVM does not
+//! support. So even though the man pages say this sort of use is possible, we must report UB.
 //@ignore-target-windows: No libc on Windows
+//@normalize-stderr-test: "size [0-9]+ and alignment" -> "size SIZE and alignment"
 
 fn main() {
     unsafe {
@@ -13,6 +15,6 @@ fn main() {
             0,
         );
         libc::munmap(ptr, 1);
-        //~^ ERROR: unsupported operation
+        //~^ ERROR: Undefined Behavior
     }
 }
diff --git a/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr b/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr
index 14eb9d32053..39825eb27c0 100644
--- a/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr
+++ b/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr
@@ -1,29 +1,15 @@
-warning: integer-to-pointer cast
+error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size SIZE and alignment ALIGN, but gave size SIZE and alignment ALIGN
   --> $DIR/munmap_partial.rs:LL:CC
    |
 LL |         libc::munmap(ptr, 1);
-   |         ^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+   |         ^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size SIZE and alignment ALIGN, but gave size SIZE and alignment ALIGN
    |
-   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::from_exposed_addr`,
-   = help: which means that Miri might miss pointer bugs in this program.
-   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html for more details on that operation.
-   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
-   = help: You can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `from_exposed_addr` semantics.
-   = help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
-   = note: BACKTRACE:
-   = note: inside `main` at $DIR/munmap_partial.rs:LL:CC
-
-error: unsupported operation: Miri only supports munmap calls that exactly unmap a region previously returned by mmap
-  --> $DIR/munmap_partial.rs:LL:CC
-   |
-LL |         libc::munmap(ptr, 1);
-   |         ^^^^^^^^^^^^^^^^^^^^ Miri only supports munmap calls that exactly unmap a region previously returned by mmap
-   |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = 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 $DIR/munmap_partial.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; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/src/tools/miri/tests/pass-dep/shims/mmap.rs b/src/tools/miri/tests/pass-dep/shims/mmap.rs
index fefbed80fd2..518f2ea3e6f 100644
--- a/src/tools/miri/tests/pass-dep/shims/mmap.rs
+++ b/src/tools/miri/tests/pass-dep/shims/mmap.rs
@@ -29,9 +29,8 @@ fn test_mmap() {
     }
     assert!(slice.iter().all(|b| *b == 1));
 
-    // Ensure that we can munmap with just an integer
-    let just_an_address = ptr::invalid_mut(ptr.addr());
-    let res = unsafe { libc::munmap(just_an_address, page_size) };
+    // Ensure that we can munmap
+    let res = unsafe { libc::munmap(ptr, page_size) };
     assert_eq!(res, 0i32);
 
     // Test all of our error conditions
diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs
index f370e658272..57d0b6a87b2 100644
--- a/src/tools/miri/tests/pass/portable-simd.rs
+++ b/src/tools/miri/tests/pass/portable-simd.rs
@@ -1,6 +1,8 @@
 //@compile-flags: -Zmiri-strict-provenance
-#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const)]
+#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const, core_intrinsics)]
 #![allow(incomplete_features, internal_features)]
+use std::intrinsics::simd as intrinsics;
+use std::ptr;
 use std::simd::{prelude::*, StdFloat};
 
 fn simd_ops_f32() {
@@ -421,6 +423,40 @@ fn simd_gather_scatter() {
     let idxs = Simd::from_array([9, 3, 0, 0]);
     Simd::from_array([-27, 82, -41, 124]).scatter(&mut vec, idxs);
     assert_eq!(vec, vec![124, 11, 12, 82, 14, 15, 16, 17, 18]);
+
+    // We call the intrinsics directly to experiment with dangling pointers and masks.
+    let val = 42u8;
+    let ptrs: Simd<*const u8, 4> =
+        Simd::from_array([ptr::null(), ptr::addr_of!(val), ptr::addr_of!(val), ptr::addr_of!(val)]);
+    let default = u8x4::splat(0);
+    let mask = i8x4::from_array([0, !0, 0, !0]);
+    let vals = unsafe { intrinsics::simd_gather(default, ptrs, mask) };
+    assert_eq!(vals, u8x4::from_array([0, 42, 0, 42]),);
+
+    let mut val1 = 0u8;
+    let mut val2 = 0u8;
+    let ptrs: Simd<*mut u8, 4> = Simd::from_array([
+        ptr::null_mut(),
+        ptr::addr_of_mut!(val1),
+        ptr::addr_of_mut!(val1),
+        ptr::addr_of_mut!(val2),
+    ]);
+    let vals = u8x4::from_array([1, 2, 3, 4]);
+    unsafe { intrinsics::simd_scatter(vals, ptrs, mask) };
+    assert_eq!(val1, 2);
+    assert_eq!(val2, 4);
+
+    // Also check what happens when `scatter` has multiple overlapping pointers.
+    let mut val = 0u8;
+    let ptrs: Simd<*mut u8, 4> = Simd::from_array([
+        ptr::addr_of_mut!(val),
+        ptr::addr_of_mut!(val),
+        ptr::addr_of_mut!(val),
+        ptr::addr_of_mut!(val),
+    ]);
+    let vals = u8x4::from_array([1, 2, 3, 4]);
+    unsafe { intrinsics::simd_scatter(vals, ptrs, mask) };
+    assert_eq!(val, 4);
 }
 
 fn simd_round() {
@@ -460,14 +496,11 @@ fn simd_round() {
 }
 
 fn simd_intrinsics() {
+    use intrinsics::*;
     extern "platform-intrinsic" {
-        fn simd_eq<T, U>(x: T, y: T) -> U;
-        fn simd_reduce_any<T>(x: T) -> bool;
-        fn simd_reduce_all<T>(x: T) -> bool;
-        fn simd_select<M, T>(m: M, yes: T, no: T) -> T;
         fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
-        fn simd_shuffle<T, IDX, U>(x: T, y: T, idx: IDX) -> U;
     }
+
     unsafe {
         // Make sure simd_eq returns all-1 for `true`
         let a = i32x4::splat(10);
@@ -503,6 +536,29 @@ fn simd_intrinsics() {
     }
 }
 
+fn simd_masked_loadstore() {
+    // The buffer is deliberarely too short, so reading the last element would be UB.
+    let buf = [3i32; 3];
+    let default = i32x4::splat(0);
+    let mask = i32x4::from_array([!0, !0, !0, 0]);
+    let vals = unsafe { intrinsics::simd_masked_load(mask, buf.as_ptr(), default) };
+    assert_eq!(vals, i32x4::from_array([3, 3, 3, 0]));
+    // Also read in a way that the *first* element is OOB.
+    let mask2 = i32x4::from_array([0, !0, !0, !0]);
+    let vals =
+        unsafe { intrinsics::simd_masked_load(mask2, buf.as_ptr().wrapping_sub(1), default) };
+    assert_eq!(vals, i32x4::from_array([0, 3, 3, 3]));
+
+    // The buffer is deliberarely too short, so writing the last element would be UB.
+    let mut buf = [42i32; 3];
+    let vals = i32x4::from_array([1, 2, 3, 4]);
+    unsafe { intrinsics::simd_masked_store(mask, buf.as_mut_ptr(), vals) };
+    assert_eq!(buf, [1, 2, 3]);
+    // Also write in a way that the *first* element is OOB.
+    unsafe { intrinsics::simd_masked_store(mask2, buf.as_mut_ptr().wrapping_sub(1), vals) };
+    assert_eq!(buf, [2, 3, 4]);
+}
+
 fn main() {
     simd_mask();
     simd_ops_f32();
@@ -513,4 +569,5 @@ fn main() {
     simd_gather_scatter();
     simd_round();
     simd_intrinsics();
+    simd_masked_loadstore();
 }