Skip to content

Commit 9376978

Browse files
committed
Auto merge of #2183 - RalfJung:better-provenance-control, r=RalfJung
adjust for better provenance control This is the Miri side of rust-lang/rust#97684.
2 parents 1c711a1 + b39e4c7 commit 9376978

29 files changed

+136
-109
lines changed

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4e725bad73747a4c93a3ac53106e4b4006edc665
1+
9d20fd109809f20c049d6895a5be27a1fbd39daa

rustup-toolchain

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ else
3030
NEW_COMMIT="$1"
3131
fi
3232
echo "$NEW_COMMIT" > rust-version
33-
shift
33+
shift || true # don't fail if shifting fails
3434

3535
# Check if we already are at that commit.
3636
CUR_COMMIT=$(rustc +miri --version -v 2>/dev/null | egrep "^commit-hash: " | cut -d " " -f 2)

src/diagnostics.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,16 @@ pub fn report_error<'tcx, 'mir>(
229229
};
230230
#[rustfmt::skip]
231231
let helps = match e.kind() {
232-
Unsupported(UnsupportedOpInfo::ThreadLocalStatic(_) | UnsupportedOpInfo::ReadExternStatic(_)) =>
232+
Unsupported(
233+
UnsupportedOpInfo::ThreadLocalStatic(_) |
234+
UnsupportedOpInfo::ReadExternStatic(_)
235+
) =>
233236
panic!("Error should never be raised by Miri: {:?}", e.kind()),
234-
Unsupported(_) =>
237+
Unsupported(
238+
UnsupportedOpInfo::Unsupported(_) |
239+
UnsupportedOpInfo::PartialPointerOverwrite(_) |
240+
UnsupportedOpInfo::ReadPointerAsBytes
241+
) =>
235242
vec![(None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"))],
236243
UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. })
237244
if ecx.machine.check_alignment == AlignmentCheck::Symbolic
@@ -245,7 +252,8 @@ pub fn report_error<'tcx, 'mir>(
245252
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
246253
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
247254
],
248-
_ => vec![],
255+
InvalidProgram(_) | ResourceExhaustion(_) | MachineStop(_) =>
256+
vec![],
249257
};
250258
(Some(title), helps)
251259
}

src/helpers.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
681681
// FIXME: We are re-getting the allocation each time around the loop.
682682
// Would be nice if we could somehow "extend" an existing AllocRange.
683683
let alloc = this.get_ptr_alloc(ptr.offset(len, this)?, size1, Align::ONE)?.unwrap(); // not a ZST, so we will get a result
684-
let byte = alloc.read_scalar(alloc_range(Size::ZERO, size1))?.to_u8()?;
684+
let byte = alloc.read_integer(Size::ZERO, size1)?.to_u8()?;
685685
if byte == 0 {
686686
break;
687687
} else {
@@ -703,7 +703,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
703703
// FIXME: We are re-getting the allocation each time around the loop.
704704
// Would be nice if we could somehow "extend" an existing AllocRange.
705705
let alloc = this.get_ptr_alloc(ptr, size2, align2)?.unwrap(); // not a ZST, so we will get a result
706-
let wchar = alloc.read_scalar(alloc_range(Size::ZERO, size2))?.to_u16()?;
706+
let wchar = alloc.read_integer(Size::ZERO, size2)?.to_u16()?;
707707
if wchar == 0 {
708708
break;
709709
} else {

tests/fail/branchless-select-i128-pointer.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ fn main() {
99
for &my_bool in &[true, false] {
1010
let mask = -(my_bool as TwoPtrs); // false -> 0, true -> -1 aka !0
1111
// This is branchless code to select one or the other pointer.
12-
// For now, Miri brafs on it, but if this code ever passes we better make sure it behaves correctly.
12+
// However, it drops provenance when transmuting to TwoPtrs, so this is UB.
1313
let val = unsafe {
14-
transmute::<_, &str>(
15-
!mask & transmute::<_, TwoPtrs>("false !") | mask & transmute::<_, TwoPtrs>("true !"), //~ERROR encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes
14+
transmute::<_, &str>( //~ERROR type validation failed: encountered a dangling reference
15+
!mask & transmute::<_, TwoPtrs>("false !") | mask & transmute::<_, TwoPtrs>("true !"),
1616
)
1717
};
1818
println!("{}", val);

tests/fail/branchless-select-i128-pointer.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
error: Undefined Behavior: type validation failed: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes
1+
error: Undefined Behavior: type validation failed: encountered a dangling reference (address $HEX is unallocated)
22
--> $DIR/branchless-select-i128-pointer.rs:LL:CC
33
|
4-
LL | !mask & transmute::<_, TwoPtrs>("false !") | mask & transmute::<_, TwoPtrs>("true !"),
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes
4+
LL | / transmute::<_, &str>(
5+
LL | | !mask & transmute::<_, TwoPtrs>("false !") | mask & transmute::<_, TwoPtrs>("true !"),
6+
LL | | )
7+
| |_____________^ type validation failed: encountered a dangling reference (address $HEX is unallocated)
68
|
79
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
810
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/fail/pointer_partial_overwrite.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
33

44
// Test what happens when we overwrite parts of a pointer.
5-
// Also see <https://github.com/rust-lang/rust/issues/87184>.
5+
// Also see <https://github.com/rust-lang/miri/issues/2181>.
66

77
fn main() {
88
let mut p = &42;

tests/fail/pointer_partial_read.rs

-9
This file was deleted.

tests/fail/pointer_partial_read.stderr

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// compile-flags: -Zmiri-permissive-provenance -Zmiri-disable-stacked-borrows
2+
#![feature(strict_provenance)]
3+
4+
use std::mem;
5+
6+
// This is the example from
7+
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/286#issuecomment-1085144431>.
8+
9+
unsafe fn deref(left: *const u8, right: *const u8) {
10+
let left_int: usize = mem::transmute(left);
11+
let right_int: usize = mem::transmute(right);
12+
if left_int == right_int {
13+
// The compiler is allowed to replace `left_int` by `right_int` here...
14+
let left_ptr: *const u8 = mem::transmute(left_int);
15+
// ...which however means here it could be dereferencing the wrong pointer.
16+
let _val = *left_ptr; //~ERROR dereferencing pointer failed
17+
}
18+
}
19+
20+
fn main() {
21+
let ptr1 = &0u8 as *const u8;
22+
let ptr2 = &1u8 as *const u8;
23+
unsafe {
24+
// Two pointers with the same address but different provenance.
25+
deref(ptr1, ptr2.with_addr(ptr1.addr()));
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: dereferencing pointer failed: $HEX is not a valid pointer
2+
--> $DIR/permissive_provenance_transmute.rs:LL:CC
3+
|
4+
LL | let _val = *left_ptr;
5+
| ^^^^^^^^^ dereferencing pointer failed: $HEX is not a valid pointer
6+
|
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
9+
10+
= note: inside `deref` at $DIR/permissive_provenance_transmute.rs:LL:CC
11+
note: inside `main` at $DIR/permissive_provenance_transmute.rs:LL:CC
12+
--> $DIR/permissive_provenance_transmute.rs:LL:CC
13+
|
14+
LL | deref(ptr1, ptr2.with_addr(ptr1.addr()));
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to previous error
20+
+5-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// compile-flags: -Zmiri-permissive-provenance -Zmiri-disable-stacked-borrows -Zmiri-allow-ptr-int-transmute
1+
// compile-flags: -Zmiri-permissive-provenance -Zmiri-disable-stacked-borrows
2+
#![feature(strict_provenance)]
23

34
fn main() {
45
let x: i32 = 3;
56
let x_ptr = &x as *const i32;
67

7-
// TODO: switch this to addr() once we intrinsify it
8-
let x_usize: usize = unsafe { std::mem::transmute(x_ptr) };
9-
// Cast back a pointer that did *not* get exposed.
10-
let ptr = x_usize as *const i32;
8+
let x_usize: usize = x_ptr.addr();
9+
// Cast back an address that did *not* get exposed.
10+
let ptr = std::ptr::from_exposed_addr::<i32>(x_usize);
1111
assert_eq!(unsafe { *ptr }, 3); //~ ERROR Undefined Behavior: dereferencing pointer failed
1212
}

tests/fail/provenance/strict_provenance_transmute.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ use std::mem;
77
// <https://github.com/rust-lang/unsafe-code-guidelines/issues/286#issuecomment-1085144431>.
88

99
unsafe fn deref(left: *const u8, right: *const u8) {
10-
let left_int: usize = mem::transmute(left); //~ERROR expected plain (non-pointer) bytes
10+
let left_int: usize = mem::transmute(left);
1111
let right_int: usize = mem::transmute(right);
1212
if left_int == right_int {
1313
// The compiler is allowed to replace `left_int` by `right_int` here...
1414
let left_ptr: *const u8 = mem::transmute(left_int);
1515
// ...which however means here it could be dereferencing the wrong pointer.
16-
let _val = *left_ptr;
16+
let _val = *left_ptr; //~ERROR dereferencing pointer failed
1717
}
1818
}
1919

tests/fail/provenance/strict_provenance_transmute.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: type validation failed: encountered pointer to $HEX[ALLOC]<TAG>, but expected plain (non-pointer) bytes
1+
error: Undefined Behavior: dereferencing pointer failed: $HEX is not a valid pointer
22
--> $DIR/strict_provenance_transmute.rs:LL:CC
33
|
4-
LL | let left_int: usize = mem::transmute(left);
5-
| ^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to $HEX[ALLOC]<TAG>, but expected plain (non-pointer) bytes
4+
LL | let _val = *left_ptr;
5+
| ^^^^^^^^^ dereferencing pointer failed: $HEX is not a valid pointer
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+8-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
// compile-flags: -Zmiri-allow-ptr-int-transmute
21
// A callee may not read the destination of our `&mut` without us noticing.
32
// Thise code got carefully checked to not introduce any reborrows
43
// that are not explicit in the source. Let's hope the compiler does not break this later!
54

6-
#![feature(untagged_unions)]
7-
85
use std::mem;
96

7+
union HiddenRef {
8+
// We avoid retagging at this type, so shared vs mutable does not matter.
9+
r: &'static i32,
10+
}
11+
1012
fn main() {
1113
let mut x: i32 = 15;
1214
let xref1 = &mut x;
13-
let xref1_sneaky: usize = unsafe { mem::transmute_copy(&xref1) };
15+
let xref1_sneaky: HiddenRef = unsafe { mem::transmute_copy(&xref1) };
1416
// Derived from `xref1`, so using raw value is still ok, ...
1517
let xref2 = &mut *xref1;
1618
callee(xref1_sneaky);
@@ -19,14 +21,8 @@ fn main() {
1921
//~^ ERROR: borrow stack
2022
}
2123

22-
fn callee(xref1: usize) {
23-
// Transmuting through a union to avoid retagging.
24-
union UsizeToRef {
25-
from: usize,
26-
to: &'static mut i32,
27-
}
28-
let xref1 = UsizeToRef { from: xref1 };
24+
fn callee(xref1: HiddenRef) {
2925
// Doing the deref and the transmute (through the union) in the same place expression
3026
// should avoid retagging.
31-
let _val = unsafe { *xref1.to };
27+
let _val = unsafe { *xref1.r };
3228
}

tests/fail/stacked_borrows/illegal_read3.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ LL | let xref2 = &mut *xref1;
1717
help: <TAG> was later invalidated at offsets [0x0..0x4]
1818
--> $DIR/illegal_read3.rs:LL:CC
1919
|
20-
LL | let _val = unsafe { *xref1.to };
21-
| ^^^^^^^^^
20+
LL | let _val = unsafe { *xref1.r };
21+
| ^^^^^^^^
2222
= note: inside `main` at $DIR/illegal_read3.rs:LL:CC
2323

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

tests/fail/transmute-pair-uninit.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// compile-flags: -Zmiri-allow-uninit-numbers
21
#![feature(core_intrinsics)]
32

43
use std::mem;
@@ -18,6 +17,6 @@ fn main() {
1817
assert_eq!(byte, 0);
1918
}
2019
let v = unsafe { *z.offset(first_undef) };
20+
//~^ ERROR uninitialized
2121
if v == 0 { println!("it is zero"); }
22-
//~^ ERROR this operation requires initialized memory
2322
}

tests/fail/transmute-pair-uninit.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
1+
error: Undefined Behavior: type validation failed: encountered uninitialized bytes, but expected initialized bytes
22
--> $DIR/transmute-pair-uninit.rs:LL:CC
33
|
4-
LL | if v == 0 { println!("it is zero"); }
5-
| ^^^^^^ using uninitialized data, but this operation requires initialized memory
4+
LL | let v = unsafe { *z.offset(first_undef) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized bytes
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/fail/transmute_fat1.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// This should fail even without validation
2-
// compile-flags: -Zmiri-disable-validation
1+
// error-pattern: type validation failed: encountered a pointer
32

43
fn main() {
54
#[cfg(target_pointer_width="64")]
@@ -10,5 +9,5 @@ fn main() {
109
let bad = unsafe {
1110
std::mem::transmute::<&[u8], [u8; 8]>(&[1u8])
1211
};
13-
let _val = bad[0] + bad[bad.len()-1]; //~ ERROR unable to turn pointer into raw bytes
12+
let _val = bad[0] + bad[bad.len()-1];
1413
}

tests/fail/transmute_fat1.stderr

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
error: unsupported operation: unable to turn pointer into raw bytes
1+
error: Undefined Behavior: type validation failed: encountered a pointer, but expected plain (non-pointer) bytes
22
--> $DIR/transmute_fat1.rs:LL:CC
33
|
4-
LL | let _val = bad[0] + bad[bad.len()-1];
5-
| ^^^^^^ unable to turn pointer into raw bytes
4+
LL | std::mem::transmute::<&[u8], [u8; 16]>(&[1u8])
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected plain (non-pointer) bytes
66
|
7-
= 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
89

910
= note: inside `main` at $DIR/transmute_fat1.rs:LL:CC
1011

tests/fail/uninit_byte_read.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
// compile-flags: -Zmiri-allow-uninit-numbers
21
fn main() {
32
let v: Vec<u8> = Vec::with_capacity(10);
4-
let undef = unsafe { *v.get_unchecked(5) };
5-
let x = undef + 1; //~ ERROR this operation requires initialized memory
3+
let undef = unsafe { *v.get_unchecked(5) }; //~ ERROR uninitialized
4+
let x = undef + 1;
65
panic!("this should never print: {}", x);
76
}

tests/fail/uninit_byte_read.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
1+
error: Undefined Behavior: type validation failed: encountered uninitialized bytes, but expected initialized bytes
22
--> $DIR/uninit_byte_read.rs:LL:CC
33
|
4-
LL | let x = undef + 1;
5-
| ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
4+
LL | let undef = unsafe { *v.get_unchecked(5) };
5+
| ^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized bytes
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/fail/validity/invalid_enum_tag_256variants_uninit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Even when uninit numbers are allowed, this enum is not.
12
// compile-flags: -Zmiri-allow-uninit-numbers
23
#![allow(unused, deprecated, invalid_value)]
34

tests/fail/validity/ptr_integer_transmute.rs

-4
This file was deleted.

tests/fail/validity/ptr_integer_transmute.stderr

-15
This file was deleted.

tests/pass/intptrcast.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// compile-flags: -Zmiri-allow-ptr-int-transmute
2-
3-
// This returns a miri pointer at type usize, if the argument is a proper pointer
1+
// This strips provenance
42
fn transmute_ptr_to_int<T>(x: *const T) -> usize {
53
unsafe { std::mem::transmute(x) }
64
}
@@ -39,7 +37,7 @@ fn transmute() {
3937
// transmuting.
4038
let a: *const i32 = &42;
4139
let b = transmute_ptr_to_int(a) as u8;
42-
let c = a as usize as u8;
40+
let c = a as u8;
4341
assert_eq!(b, c);
4442
}
4543

0 commit comments

Comments
 (0)