1 //@compile-flags: -Zmiri-permissive-provenance
2 #![feature(strict_provenance)]
5 // Just to make sure that casting a ref to raw, to int and back to raw
6 // and only then using it works. This rules out ideas like "do escape-to-raw lazily";
7 // after casting to int and back, we lost the tag that could have let us do that.
11 let xraw = xref as *mut i32 as usize as *mut i32;
12 assert_eq!(unsafe { *xraw }, 3);
15 /// Ensure that we do not just pick the topmost possible item on int2ptr casts.
16 fn example(variant: bool) {
18 fn not_so_innocent(x: &mut u32) -> usize {
19 let x_raw4 = x as *mut u32;
25 let x_unique1 = &mut c;
28 let x_raw2 = x_unique1 as *mut u32;
29 let x_raw2_addr = x_raw2.expose_addr();
30 // [..., Unique(1), SharedRW(2)]
32 let x_unique3 = &mut *x_raw2;
33 // [.., Unique(1), SharedRW(2), Unique(3)]
35 assert_eq!(not_so_innocent(x_unique3), x_raw2_addr);
36 // [.., Unique(1), SharedRW(2), Unique(3), ..., SharedRW(4)]
38 // Do an int2ptr cast. This can pick tag 2 or 4 (the two previously exposed tags).
39 // 4 is the "obvious" choice (topmost tag, what we used to do with untagged pointers).
40 // And indeed if `variant == true` it is the only possible choice.
41 // But if `variant == false` then 2 is the only possible choice!
42 let x_wildcard = ptr::from_exposed_addr_mut::<i32>(x_raw2_addr);
45 // If we picked 2, this will invalidate 3.
47 // Now we use 3. Only possible if above we picked 4.
50 // This invalidates tag 4.
52 // Now try to write with the "guessed" tag; it must be 2.
61 let root_raw = root as *mut i32;
62 let addr1 = root_raw as usize;
63 let child = &mut *root_raw;
64 let child_raw = child as *mut i32;
65 let addr2 = child_raw as usize;
66 assert_eq!(addr1, addr2);
68 *(addr2 as *mut i32) -= 2; // picks child_raw
71 *(addr1 as *mut i32) += 2; // picks root_raw
73 // Value should be unchanged.
74 assert_eq!(*root, 42);