Skip to content

Commit 94920de

Browse files
committed
Add example of reversed pointer bytes being rejected
Let's add an example demonstrating that reversing the order of pointer bytes causes compilation to fail, even though all bytes are present. The compiler tracks the position of each byte within its original pointer and only accepts pointers when reassembled in the correct order. This example copies a pointer byte-by-byte in reverse order into the padding of a struct, which fails because the fragment indices don't match up to form a valid pointer. Context: rust-lang/rust#144081
1 parent efaf9f2 commit 94920de

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

src/const_eval.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,35 @@ const C: Pair = unsafe {
265265
>
266266
> This restriction ensures that any bytes with provenance in the final value represent complete, valid pointers. The compiler cannot support pointer fragments because it would be unable to reason about them at compile time.
267267
268+
> [!NOTE]
269+
>
270+
> Reversing the order of the pointer bytes also causes compilation to fail, even though all bytes are present:
271+
>
272+
> ```rust,compile_fail
273+
> # use std::mem::MaybeUninit;
274+
> # #[repr(C)]
275+
> # struct Pair {
276+
> # x: u128,
277+
> # y: MaybeUninit<u64>,
278+
> # }
279+
> const C: Pair = unsafe {
280+
> // ^^^^^^^ ERROR: Partial pointer in final value of constant.
281+
> let mut m = MaybeUninit::<Pair>::uninit();
282+
> let ptr: *const u8 = &0;
283+
> let ptr_bytes = &ptr as *const _ as *const MaybeUninit<u8>;
284+
> // Write pointer bytes in reverse order into the padding.
285+
> let dst = m.as_mut_ptr().cast::<MaybeUninit<u8>>().add(24);
286+
> let mut i = 0;
287+
> while i < 8 {
288+
> dst.add(i).write(ptr_bytes.add(7 - i).read());
289+
> i += 1;
290+
> }
291+
> (*m.as_mut_ptr()).x = 0;
292+
> (*m.as_mut_ptr()).y = MaybeUninit::new(0);
293+
> m.assume_init()
294+
> };
295+
> ```
296+
268297
> [!NOTE]
269298
> Manually initializing (e.g., zeroing) the padding bytes ensures the final value is accepted:
270299
>

0 commit comments

Comments
 (0)