Skip to content

Commit ea7ef7b

Browse files
committed
Auto merge of rust-lang#119315 - RalfJung:miri, r=RalfJung
Miri subtree update r? `@ghost`
2 parents a815c3b + 4658d38 commit ea7ef7b

File tree

13 files changed

+155
-150
lines changed

13 files changed

+155
-150
lines changed

src/tools/miri/miri-script/src/commands.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ impl Command {
344344
println!(
345345
// Open PR with `subtree update` title to silence the `no-merges` triagebot check
346346
// See https://github.com/rust-lang/rust/pull/114157
347-
" https://github.com/rust-lang/rust/compare/{github_user}:{branch}?quick_pull=1&title=Miri+subtree+update"
347+
" https://github.com/rust-lang/rust/compare/{github_user}:{branch}?quick_pull=1&title=Miri+subtree+update&body=r?+@ghost"
348348
);
349349

350350
drop(josh);
@@ -478,7 +478,11 @@ impl Command {
478478
// Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
479479
// that we set the MIRI_SYSROOT up the right way.
480480
use itertools::Itertools;
481-
let target = flags.iter().tuple_windows().find(|(first, _)| first == &"--target");
481+
let target = flags
482+
.iter()
483+
.take_while(|arg| *arg != "--")
484+
.tuple_windows()
485+
.find(|(first, _)| *first == "--target");
482486
if let Some((_, target)) = target {
483487
// Found it!
484488
e.sh.set_var("MIRI_TEST_TARGET", target);
@@ -487,6 +491,10 @@ impl Command {
487491
let miriflags = e.sh.var("MIRIFLAGS").unwrap_or_default();
488492
e.sh.set_var("MIRIFLAGS", format!("{miriflags} --target {target}"));
489493
}
494+
// Scan for "--edition" (we'll set one ourselves if that flag is not present).
495+
let have_edition =
496+
flags.iter().take_while(|arg| *arg != "--").any(|arg| *arg == "--edition");
497+
490498
// Prepare a sysroot.
491499
e.build_miri_sysroot(/* quiet */ true)?;
492500

@@ -496,15 +504,16 @@ impl Command {
496504
let miri_flags = flagsplit(&miri_flags);
497505
let toolchain = &e.toolchain;
498506
let extra_flags = &e.cargo_extra_flags;
507+
let edition_flags = (!have_edition).then_some("--edition=2021"); // keep in sync with `compiletest.rs`.`
499508
if dep {
500509
cmd!(
501510
e.sh,
502-
"cargo +{toolchain} --quiet test --test compiletest {extra_flags...} --manifest-path {miri_manifest} -- --miri-run-dep-mode {miri_flags...} {flags...}"
511+
"cargo +{toolchain} --quiet test --test compiletest {extra_flags...} --manifest-path {miri_manifest} -- --miri-run-dep-mode {miri_flags...} {edition_flags...} {flags...}"
503512
).quiet().run()?;
504513
} else {
505514
cmd!(
506515
e.sh,
507-
"cargo +{toolchain} --quiet run {extra_flags...} --manifest-path {miri_manifest} -- {miri_flags...} {flags...}"
516+
"cargo +{toolchain} --quiet run {extra_flags...} --manifest-path {miri_manifest} -- {miri_flags...} {edition_flags...} {flags...}"
508517
).quiet().run()?;
509518
}
510519
Ok(())

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
604f185fae9a4b0edf7e28f616a0f53880f8f074
1+
2271c26e4a8e062bb00d709d0ccb5846e0c341b9

src/tools/miri/src/shims/intrinsics/simd.rs

+48
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,54 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
656656
}
657657
}
658658
}
659+
"masked_load" => {
660+
let [mask, ptr, default] = check_arg_count(args)?;
661+
let (mask, mask_len) = this.operand_to_simd(mask)?;
662+
let ptr = this.read_pointer(ptr)?;
663+
let (default, default_len) = this.operand_to_simd(default)?;
664+
let (dest, dest_len) = this.place_to_simd(dest)?;
665+
666+
assert_eq!(dest_len, mask_len);
667+
assert_eq!(dest_len, default_len);
668+
669+
for i in 0..dest_len {
670+
let mask = this.read_immediate(&this.project_index(&mask, i)?)?;
671+
let default = this.read_immediate(&this.project_index(&default, i)?)?;
672+
let dest = this.project_index(&dest, i)?;
673+
674+
let val = if simd_element_to_bool(mask)? {
675+
// Size * u64 is implemented as always checked
676+
#[allow(clippy::arithmetic_side_effects)]
677+
let ptr = ptr.wrapping_offset(dest.layout.size * i, this);
678+
let place = this.ptr_to_mplace(ptr, dest.layout);
679+
this.read_immediate(&place)?
680+
} else {
681+
default
682+
};
683+
this.write_immediate(*val, &dest)?;
684+
}
685+
}
686+
"masked_store" => {
687+
let [mask, ptr, vals] = check_arg_count(args)?;
688+
let (mask, mask_len) = this.operand_to_simd(mask)?;
689+
let ptr = this.read_pointer(ptr)?;
690+
let (vals, vals_len) = this.operand_to_simd(vals)?;
691+
692+
assert_eq!(mask_len, vals_len);
693+
694+
for i in 0..vals_len {
695+
let mask = this.read_immediate(&this.project_index(&mask, i)?)?;
696+
let val = this.read_immediate(&this.project_index(&vals, i)?)?;
697+
698+
if simd_element_to_bool(mask)? {
699+
// Size * u64 is implemented as always checked
700+
#[allow(clippy::arithmetic_side_effects)]
701+
let ptr = ptr.wrapping_offset(val.layout.size * i, this);
702+
let place = this.ptr_to_mplace(ptr, val.layout);
703+
this.write_immediate(*val, &place)?
704+
};
705+
}
706+
}
659707

660708
name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"),
661709
}

src/tools/miri/src/shims/unix/linux/mem.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
1515
) -> InterpResult<'tcx, Scalar<Provenance>> {
1616
let this = self.eval_context_mut();
1717

18-
let old_address = this.read_target_usize(old_address)?;
18+
let old_address = this.read_pointer(old_address)?;
1919
let old_size = this.read_target_usize(old_size)?;
2020
let new_size = this.read_target_usize(new_size)?;
2121
let flags = this.read_scalar(flags)?.to_i32()?;
2222

2323
// old_address must be a multiple of the page size
2424
#[allow(clippy::arithmetic_side_effects)] // PAGE_SIZE is nonzero
25-
if old_address % this.machine.page_size != 0 || new_size == 0 {
25+
if old_address.addr().bytes() % this.machine.page_size != 0 || new_size == 0 {
2626
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
2727
return Ok(this.eval_libc("MAP_FAILED"));
2828
}
@@ -41,7 +41,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
4141
return Ok(this.eval_libc("MAP_FAILED"));
4242
}
4343

44-
let old_address = Machine::ptr_from_addr_cast(this, old_address)?;
4544
let align = this.machine.page_align();
4645
let ptr = this.reallocate_ptr(
4746
old_address,
@@ -59,8 +58,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
5958
)
6059
.unwrap();
6160
}
62-
// Memory mappings are always exposed
63-
Machine::expose_ptr(this, ptr)?;
6461

6562
Ok(Scalar::from_pointer(ptr, this))
6663
}

src/tools/miri/src/shims/unix/mem.rs

+14-31
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
//! mmap/munmap behave a lot like alloc/dealloc, and for simple use they are exactly
77
//! equivalent. That is the only part we support: no MAP_FIXED or MAP_SHARED or anything
88
//! else that goes beyond a basic allocation API.
9+
//!
10+
//! Note that in addition to only supporting malloc-like calls to mmap, we only support free-like
11+
//! calls to munmap, but for a very different reason. In principle, according to the man pages, it
12+
//! is possible to unmap arbitrary regions of address space. But in a high-level language like Rust
13+
//! this amounts to partial deallocation, which LLVM does not support. So any attempt to call our
14+
//! munmap shim which would partily unmap a region of address space previously mapped by mmap will
15+
//! report UB.
916
1017
use crate::{helpers::round_to_next_multiple_of, *};
1118
use rustc_target::abi::Size;
@@ -100,8 +107,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
100107
std::iter::repeat(0u8).take(usize::try_from(map_length).unwrap()),
101108
)
102109
.unwrap();
103-
// Memory mappings don't use provenance, and are always exposed.
104-
Machine::expose_ptr(this, ptr)?;
105110

106111
Ok(Scalar::from_pointer(ptr, this))
107112
}
@@ -113,43 +118,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
113118
) -> InterpResult<'tcx, Scalar<Provenance>> {
114119
let this = self.eval_context_mut();
115120

116-
let addr = this.read_target_usize(addr)?;
121+
let addr = this.read_pointer(addr)?;
117122
let length = this.read_target_usize(length)?;
118123

119-
// addr must be a multiple of the page size
124+
// addr must be a multiple of the page size, but apart from that munmap is just implemented
125+
// as a dealloc.
120126
#[allow(clippy::arithmetic_side_effects)] // PAGE_SIZE is nonzero
121-
if addr % this.machine.page_size != 0 {
127+
if addr.addr().bytes() % this.machine.page_size != 0 {
122128
this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
123129
return Ok(Scalar::from_i32(-1));
124130
}
125131

126-
let length = round_to_next_multiple_of(length, this.machine.page_size);
127-
128-
let ptr = Machine::ptr_from_addr_cast(this, addr)?;
129-
130-
let Ok(ptr) = ptr.into_pointer_or_addr() else {
131-
throw_unsup_format!("Miri only supports munmap on memory allocated directly by mmap");
132-
};
133-
let Some((alloc_id, offset, _prov)) = Machine::ptr_get_alloc(this, ptr) else {
134-
throw_unsup_format!("Miri only supports munmap on memory allocated directly by mmap");
135-
};
136-
137-
// Elsewhere in this function we are careful to check what we can and throw an unsupported
138-
// error instead of Undefined Behavior when use of this function falls outside of the
139-
// narrow scope we support. We deliberately do not check the MemoryKind of this allocation,
140-
// because we want to report UB on attempting to unmap memory that Rust "understands", such
141-
// the stack, heap, or statics.
142-
let (_kind, alloc) = this.memory.alloc_map().get(alloc_id).unwrap();
143-
if offset != Size::ZERO || alloc.len() as u64 != length {
144-
throw_unsup_format!(
145-
"Miri only supports munmap calls that exactly unmap a region previously returned by mmap"
146-
);
147-
}
148-
149-
let len = Size::from_bytes(alloc.len() as u64);
132+
let length = Size::from_bytes(round_to_next_multiple_of(length, this.machine.page_size));
150133
this.deallocate_ptr(
151-
ptr.into(),
152-
Some((len, this.machine.page_align())),
134+
addr,
135+
Some((length, this.machine.page_align())),
153136
MemoryKind::Machine(MiriMemoryKind::Mmap),
154137
)?;
155138

src/tools/miri/tests/compiletest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
9191
mode,
9292
program,
9393
out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("ui"),
94-
edition: Some("2021".into()),
94+
edition: Some("2021".into()), // keep in sync with `./miri run`
9595
threads: std::env::var("MIRI_TEST_THREADS")
9696
.ok()
9797
.map(|threads| NonZeroUsize::new(threads.parse().unwrap()).unwrap()),

src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr

+1-16
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
1-
warning: integer-to-pointer cast
2-
--> $DIR/mmap_use_after_munmap.rs:LL:CC
3-
|
4-
LL | libc::munmap(ptr, 4096);
5-
| ^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
6-
|
7-
= help: This program is using integer-to-pointer casts or (equivalently) `ptr::from_exposed_addr`,
8-
= help: which means that Miri might miss pointer bugs in this program.
9-
= help: See https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html for more details on that operation.
10-
= 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.
11-
= help: You can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `from_exposed_addr` semantics.
12-
= help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
13-
= note: BACKTRACE:
14-
= note: inside `main` at $DIR/mmap_use_after_munmap.rs:LL:CC
15-
161
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
172
--> $DIR/mmap_use_after_munmap.rs:LL:CC
183
|
@@ -43,5 +28,5 @@ LL | libc::munmap(ptr, 4096);
4328

4429
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
4530

46-
error: aborting due to 1 previous error; 1 warning emitted
31+
error: aborting due to 1 previous error
4732

src/tools/miri/tests/fail-dep/shims/munmap.rs

-22
This file was deleted.

src/tools/miri/tests/fail-dep/shims/munmap.stderr

-39
This file was deleted.

src/tools/miri/tests/fail-dep/shims/munmap_partial.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
//! Our mmap/munmap support is a thin wrapper over Interpcx::allocate_ptr. Since the underlying
2-
//! layer has much more UB than munmap does, we need to be sure we throw an unsupported error here.
1+
//! The man pages for mmap/munmap suggest that it is possible to partly unmap a previously-mapped
2+
//! region of addres space, but to LLVM that would be partial deallocation, which LLVM does not
3+
//! support. So even though the man pages say this sort of use is possible, we must report UB.
34
//@ignore-target-windows: No libc on Windows
5+
//@normalize-stderr-test: "size [0-9]+ and alignment" -> "size SIZE and alignment"
46

57
fn main() {
68
unsafe {
@@ -13,6 +15,6 @@ fn main() {
1315
0,
1416
);
1517
libc::munmap(ptr, 1);
16-
//~^ ERROR: unsupported operation
18+
//~^ ERROR: Undefined Behavior
1719
}
1820
}
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,15 @@
1-
warning: integer-to-pointer cast
1+
error: Undefined Behavior: incorrect layout on deallocation: ALLOC has size SIZE and alignment ALIGN, but gave size SIZE and alignment ALIGN
22
--> $DIR/munmap_partial.rs:LL:CC
33
|
44
LL | libc::munmap(ptr, 1);
5-
| ^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
5+
| ^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: ALLOC has size SIZE and alignment ALIGN, but gave size SIZE and alignment ALIGN
66
|
7-
= help: This program is using integer-to-pointer casts or (equivalently) `ptr::from_exposed_addr`,
8-
= help: which means that Miri might miss pointer bugs in this program.
9-
= help: See https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html for more details on that operation.
10-
= 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.
11-
= help: You can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `from_exposed_addr` semantics.
12-
= help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
13-
= note: BACKTRACE:
14-
= note: inside `main` at $DIR/munmap_partial.rs:LL:CC
15-
16-
error: unsupported operation: Miri only supports munmap calls that exactly unmap a region previously returned by mmap
17-
--> $DIR/munmap_partial.rs:LL:CC
18-
|
19-
LL | libc::munmap(ptr, 1);
20-
| ^^^^^^^^^^^^^^^^^^^^ Miri only supports munmap calls that exactly unmap a region previously returned by mmap
21-
|
22-
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
239
= note: BACKTRACE:
2410
= note: inside `main` at $DIR/munmap_partial.rs:LL:CC
2511

2612
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
2713

28-
error: aborting due to 1 previous error; 1 warning emitted
14+
error: aborting due to 1 previous error
2915

src/tools/miri/tests/pass-dep/shims/mmap.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ fn test_mmap() {
2929
}
3030
assert!(slice.iter().all(|b| *b == 1));
3131

32-
// Ensure that we can munmap with just an integer
33-
let just_an_address = ptr::invalid_mut(ptr.addr());
34-
let res = unsafe { libc::munmap(just_an_address, page_size) };
32+
// Ensure that we can munmap
33+
let res = unsafe { libc::munmap(ptr, page_size) };
3534
assert_eq!(res, 0i32);
3635

3736
// Test all of our error conditions

0 commit comments

Comments
 (0)