Skip to content

Commit d4d85a8

Browse files
committed
don't UB on dangling ptr deref, instead check inbounds on projections
1 parent babeda8 commit d4d85a8

File tree

66 files changed

+264
-220
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+264
-220
lines changed

src/helpers.rs

-17
Original file line numberDiff line numberDiff line change
@@ -700,23 +700,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
700700

701701
let mplace = MPlaceTy::from_aligned_ptr(ptr, layout);
702702

703-
this.check_mplace(&mplace)?;
704-
705-
Ok(mplace)
706-
}
707-
708-
/// Deref' a pointer *without* checking that the place is dereferenceable.
709-
fn deref_pointer_unchecked(
710-
&self,
711-
val: &ImmTy<'tcx, Provenance>,
712-
layout: TyAndLayout<'tcx>,
713-
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
714-
let this = self.eval_context_ref();
715-
let mut mplace = this.ref_to_mplace(val)?;
716-
717-
mplace.layout = layout;
718-
mplace.align = layout.align.abi;
719-
720703
Ok(mplace)
721704
}
722705

src/machine.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
12851285
// We do need to write `uninit` so that even after the call ends, the former contents of
12861286
// this place cannot be observed any more. We do the write after retagging so that for
12871287
// Tree Borrows, this is considered to activate the new tag.
1288+
// Conveniently this also ensures that the place actually points to suitable memory.
12881289
ecx.write_uninit(&protected_place)?;
12891290
// Now we throw away the protected place, ensuring its tag is never used again.
12901291
Ok(())

src/shims/unix/linux/sync.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,8 @@ pub fn futex<'tcx>(
8585
return Ok(());
8686
}
8787

88-
// `read_timespec` will check the place when it is not null.
89-
let timeout = this.deref_pointer_unchecked(
90-
&this.read_immediate(&args[3])?,
88+
let timeout = this.deref_pointer_as(
89+
&args[3],
9190
this.libc_ty_layout("timespec"),
9291
)?;
9392
let timeout_time = if this.ptr_is_null(timeout.ptr())? {

tests/compiletest.rs

+1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ regexes! {
181181
r"0x[0-9a-fA-F]+[0-9a-fA-F]{2,2}" => "$$HEX",
182182
// erase specific alignments
183183
"alignment [0-9]+" => "alignment ALIGN",
184+
"[0-9]+ byte alignment but found [0-9]+" => "ALIGN byte alignment but found ALIGN",
184185
// erase thread caller ids
185186
r"call [0-9]+" => "call ID",
186187
// erase platform module paths

tests/fail-dep/shims/mmap_use_after_munmap.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ LL | libc::munmap(ptr, 4096);
1313
= note: BACKTRACE:
1414
= note: inside `main` at $DIR/mmap_use_after_munmap.rs:LL:CC
1515

16-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
16+
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
1717
--> $DIR/mmap_use_after_munmap.rs:LL:CC
1818
|
1919
LL | let _x = *(ptr as *mut u8);
20-
| ^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
20+
| ^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
2121
|
2222
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
2323
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/fail/alloc/reallocate-change-alloc.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
1+
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
22
--> $DIR/reallocate-change-alloc.rs:LL:CC
33
|
44
LL | let _z = *x;
5-
| ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
5+
| ^^ memory access failed: ALLOC has been freed, so this pointer is dangling
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/concurrency/thread_local_static_dealloc.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
1+
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
22
--> $DIR/thread_local_static_dealloc.rs:LL:CC
33
|
44
LL | let _val = *dangling_ptr.0;
5-
| ^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
5+
| ^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
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/dangling_pointers/dangling_pointer_addr_of.rs

-12
This file was deleted.

tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr

-26
This file was deleted.

tests/fail/dangling_pointers/dangling_pointer_deref.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
1+
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
22
--> $DIR/dangling_pointer_deref.rs:LL:CC
33
|
44
LL | let x = unsafe { *p };
5-
| ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
5+
| ^^ memory access failed: ALLOC has been freed, so this pointer is dangling
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/dangling_pointers/dangling_pointer_project_underscore.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
fn main() {
55
let p = {
66
let b = Box::new(42);
7-
&*b as *const i32
7+
&*b as *const i32 as *const (u8, u8, u8, u8)
88
};
99
unsafe {
10-
let _ = *p; //~ ERROR: has been freed
10+
let _ = (*p).1; //~ ERROR: out-of-bounds pointer arithmetic
1111
}
12-
panic!("this should never print");
1312
}

tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
1+
error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
22
--> $DIR/dangling_pointer_project_underscore.rs:LL:CC
33
|
4-
LL | let _ = *p;
5-
| ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
4+
LL | let _ = (*p).1;
5+
| ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
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/dangling_pointers/dangling_primitive.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
1+
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
22
--> $DIR/dangling_primitive.rs:LL:CC
33
|
44
LL | dbg!(*ptr);
5-
| ^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
5+
| ^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
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/dangling_pointers/dangling_zst_deref.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
1+
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
22
--> $DIR/dangling_zst_deref.rs:LL:CC
33
|
44
LL | let _x = unsafe { *p };
5-
| ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
5+
| ^^ memory access failed: ALLOC has been freed, so this pointer is dangling
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/dangling_pointers/deref-invalid-ptr.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: 0x10[noalloc] is a dangling pointer (it has no provenance)
1+
error: Undefined Behavior: out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
22
--> $DIR/deref-invalid-ptr.rs:LL:CC
33
|
44
LL | let _y = unsafe { &*x as *const u32 };
5-
| ^^^ dereferencing pointer failed: 0x10[noalloc] is a dangling pointer (it has no provenance)
5+
| ^^^ out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
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/dangling_pointers/deref-partially-dangling.rs

-8
This file was deleted.

tests/fail/dangling_pointers/deref-partially-dangling.stderr

-20
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Should be caught even without retagging
2+
//@compile-flags: -Zmiri-disable-stacked-borrows
3+
#![feature(strict_provenance)]
4+
use std::ptr::{addr_of_mut, self};
5+
6+
// Deref'ing a dangling raw pointer is fine, but for a dangling box it is not.
7+
// We do this behind a pointer indirection to potentially fool validity checking.
8+
// (This test relies on the `deref_copy` pass that lowers `**ptr` to materialize the intermediate pointer.)
9+
10+
fn main() {
11+
let mut inner = ptr::invalid::<i32>(24);
12+
let outer = addr_of_mut!(inner).cast::<Box<i32>>();
13+
// Now `outer` is a pointer to a dangling reference.
14+
// Deref'ing that should be UB.
15+
let _val = unsafe { addr_of_mut!(**outer) }; //~ERROR: dangling box
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: Undefined Behavior: constructing invalid value: encountered a dangling box (0x18[noalloc] has no provenance)
2+
--> $DIR/deref_dangling_box.rs:LL:CC
3+
|
4+
LL | let _val = unsafe { addr_of_mut!(**outer) };
5+
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x18[noalloc] has no provenance)
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+
= note: BACKTRACE:
10+
= note: inside `main` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
11+
= note: this error originates in the macro `addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
12+
13+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
14+
15+
error: aborting due to previous error
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Should be caught even without retagging
2+
//@compile-flags: -Zmiri-disable-stacked-borrows
3+
#![feature(strict_provenance)]
4+
use std::ptr::{addr_of_mut, self};
5+
6+
// Deref'ing a dangling raw pointer is fine, but for a dangling reference it is not.
7+
// We do this behind a pointer indirection to potentially fool validity checking.
8+
// (This test relies on the `deref_copy` pass that lowers `**ptr` to materialize the intermediate pointer.)
9+
10+
fn main() {
11+
let mut inner = ptr::invalid::<i32>(24);
12+
let outer = addr_of_mut!(inner).cast::<&'static mut i32>();
13+
// Now `outer` is a pointer to a dangling reference.
14+
// Deref'ing that should be UB.
15+
let _val = unsafe { addr_of_mut!(**outer) }; //~ERROR: dangling reference
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: Undefined Behavior: constructing invalid value: encountered a dangling reference (0x18[noalloc] has no provenance)
2+
--> $DIR/deref_dangling_ref.rs:LL:CC
3+
|
4+
LL | let _val = unsafe { addr_of_mut!(**outer) };
5+
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x18[noalloc] has no provenance)
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+
= note: BACKTRACE:
10+
= note: inside `main` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
11+
= note: this error originates in the macro `addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
12+
13+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
14+
15+
error: aborting due to previous error
16+
+4-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
// should find the bug even without these
2-
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
1+
// should find the bug even without retagging
2+
//@compile-flags: -Zmiri-disable-stacked-borrows
33

44
struct SliceWithHead(u8, [u8]);
55

66
fn main() {
77
let buf = [0u32; 1];
88
// We craft a wide pointer `*const SliceWithHead` such that the unsized tail is only partially allocated.
9-
// That should be UB, as the reference is not fully dereferencable.
9+
// That should lead to UB, as the reference is not fully dereferenceable.
1010
let ptr: *const SliceWithHead = unsafe { std::mem::transmute((&buf, 4usize)) };
1111
// Re-borrow that. This should be UB.
12-
let _ptr = unsafe { &*ptr }; //~ ERROR: pointer to 5 bytes starting at offset 0 is out-of-bounds
12+
let _ptr = unsafe { &*ptr }; //~ ERROR: encountered a dangling reference (going beyond the bounds of its allocation)
1313
}

tests/fail/dangling_pointers/dyn_size.stderr

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has size 4, so pointer to 5 bytes starting at offset 0 is out-of-bounds
1+
error: Undefined Behavior: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
22
--> $DIR/dyn_size.rs:LL:CC
33
|
44
LL | let _ptr = unsafe { &*ptr };
5-
| ^^^^^ dereferencing pointer failed: ALLOC has size 4, so pointer to 5 bytes starting at offset 0 is out-of-bounds
5+
| ^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
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
9-
help: ALLOC was allocated here:
10-
--> $DIR/dyn_size.rs:LL:CC
11-
|
12-
LL | let buf = [0u32; 1];
13-
| ^^^
14-
= note: BACKTRACE (of the first span):
9+
= note: BACKTRACE:
1510
= note: inside `main` at $DIR/dyn_size.rs:LL:CC
1611

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

tests/fail/dangling_pointers/maybe_null_pointer_deref_zst.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
1+
error: Undefined Behavior: memory access failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
22
--> $DIR/maybe_null_pointer_deref_zst.rs:LL:CC
33
|
44
LL | let _x: () = unsafe { *ptr };
5-
| ^^^^ dereferencing pointer failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
5+
| ^^^^ memory access failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
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/dangling_pointers/maybe_null_pointer_write_zst.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
1+
error: Undefined Behavior: memory access failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
22
--> $DIR/maybe_null_pointer_write_zst.rs:LL:CC
33
|
44
LL | unsafe { *ptr = zst_val };
5-
| ^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
5+
| ^^^^^^^^^^^^^^ memory access failed: ALLOC has size 1, so pointer at offset -2048 is out-of-bounds
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/dangling_pointers/null_pointer_deref.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
1+
error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
22
--> $DIR/null_pointer_deref.rs:LL:CC
33
|
44
LL | let x: i32 = unsafe { *std::ptr::null() };
5-
| ^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
5+
| ^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
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
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[allow(deref_nullptr)]
22
fn main() {
3-
let x: () = unsafe { *std::ptr::null() }; //~ ERROR: dereferencing pointer failed: null pointer is a dangling pointer
3+
let x: () = unsafe { *std::ptr::null() }; //~ ERROR: memory access failed: null pointer is a dangling pointer
44
panic!("this should never print: {:?}", x);
55
}

0 commit comments

Comments
 (0)