Skip to content

Commit 388606b

Browse files
committed
Auto merge of #117329 - RalfJung:offset-by-zero, r=oli-obk,scottmcm
offset: allow zero-byte offset on arbitrary pointers As per prior `@rust-lang/opsem` [discussion](rust-lang/opsem-team#10) and [FCP](rust-lang/unsafe-code-guidelines#472 (comment)): - Zero-sized reads and writes are allowed on all sufficiently aligned pointers, including the null pointer - Inbounds-offset-by-zero is allowed on all pointers, including the null pointer - `offset_from` on two pointers derived from the same allocation is always allowed when they have the same address This removes surprising UB (in particular, even C++ allows "nullptr + 0", which we currently disallow), and it brings us one step closer to an important theoretical property for our semantics ("provenance monotonicity": if operations are valid on bytes without provenance, then adding provenance can't make them invalid). The minimum LLVM we require (v17) includes https://reviews.llvm.org/D154051, so we can finally implement this. The `offset_from` change is needed to maintain the equivalence with `offset`: if `let ptr2 = ptr1.offset(N)` is well-defined, then `ptr2.offset_from(ptr1)` should be well-defined and return N. Now consider the case where N is 0 and `ptr1` dangles: we want to still allow offset_from here. I think we should change offset_from further, but that's a separate discussion. Fixes rust-lang/rust#65108 [Tracking issue](rust-lang/rust#117945) | [T-lang summary](rust-lang/rust#117329 (comment)) Cc `@nikic`
2 parents a79ce97 + c9e9916 commit 388606b

28 files changed

+64
-327
lines changed

tests/fail/dangling_pointers/dangling_zst_deref.rs

-10
This file was deleted.

tests/fail/dangling_pointers/dangling_zst_deref.stderr

-25
This file was deleted.

tests/fail/dangling_pointers/maybe_null_pointer_deref_zst.rs

-5
This file was deleted.

tests/fail/dangling_pointers/maybe_null_pointer_deref_zst.stderr

-15
This file was deleted.

tests/fail/dangling_pointers/maybe_null_pointer_write_zst.rs

-8
This file was deleted.

tests/fail/dangling_pointers/maybe_null_pointer_write_zst.stderr

-15
This file was deleted.

tests/fail/dangling_pointers/null_pointer_deref_zst.rs

-5
This file was deleted.

tests/fail/dangling_pointers/null_pointer_deref_zst.stderr

-15
This file was deleted.

tests/fail/dangling_pointers/null_pointer_write_zst.rs

-8
This file was deleted.

tests/fail/dangling_pointers/null_pointer_write_zst.stderr

-15
This file was deleted.

tests/fail/intrinsics/copy_null.rs

-15
This file was deleted.

tests/fail/intrinsics/copy_null.stderr

-15
This file was deleted.

tests/fail/intrinsics/ptr_offset_0_plus_0.rs

-9
This file was deleted.

tests/fail/intrinsics/ptr_offset_0_plus_0.stderr

-15
This file was deleted.

tests/fail/intrinsics/ptr_offset_from_oob.rs

-7
This file was deleted.

tests/fail/intrinsics/ptr_offset_from_oob.stderr

-15
This file was deleted.

tests/fail/intrinsics/ptr_offset_ptr_plus_0.rs

-7
This file was deleted.

tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr

-20
This file was deleted.

tests/fail/intrinsics/write_bytes_null.rs

-10
This file was deleted.

tests/fail/intrinsics/write_bytes_null.stderr

-15
This file was deleted.

tests/fail/zst2.rs

-12
This file was deleted.

tests/fail/zst2.stderr

-25
This file was deleted.

tests/fail/zst3.rs

-15
This file was deleted.

tests/fail/zst3.stderr

-20
This file was deleted.
File renamed without changes.

tests/fail/zst1.stderr renamed to tests/fail/zst_local_oob.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: memory access failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
2-
--> $DIR/zst1.rs:LL:CC
2+
--> $DIR/zst_local_oob.rs:LL:CC
33
|
44
LL | let _val = unsafe { *x };
55
| ^^ memory access failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 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
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/zst1.rs:LL:CC
10+
= note: inside `main` at $DIR/zst_local_oob.rs:LL:CC
1111

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

tests/pass/align_offset_symbolic.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,9 @@ fn vtable() {
118118
let parts: (*const (), *const u8) = unsafe { mem::transmute(ptr) };
119119
let vtable = parts.1;
120120
let offset = vtable.align_offset(mem::align_of::<TWOPTR>());
121-
let _vtable_aligned = vtable.wrapping_add(offset) as *const [TWOPTR; 0];
122-
// FIXME: we can't actually do the access since vtable pointers act like zero-sized allocations.
123-
// Enable the next line once https://github.com/rust-lang/rust/issues/117945 is implemented.
124-
//let _place = unsafe { &*vtable_aligned };
121+
let vtable_aligned = vtable.wrapping_add(offset) as *const [TWOPTR; 0];
122+
// Zero-sized deref, so no in-bounds requirement.
123+
let _place = unsafe { &*vtable_aligned };
125124
}
126125

127126
fn main() {

0 commit comments

Comments
 (0)