]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs
Rollup merge of #84022 - Aaron1011:remove-derive-res-fallback, r=petrochenkov
[rust.git] / src / tools / miri / tests / pass / stacked-borrows / int-to-ptr.rs
1 //@compile-flags: -Zmiri-permissive-provenance
2 #![feature(strict_provenance)]
3 use std::ptr;
4
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.
8 fn ref_raw_int_raw() {
9     let mut x = 3;
10     let xref = &mut x;
11     let xraw = xref as *mut i32 as usize as *mut i32;
12     assert_eq!(unsafe { *xraw }, 3);
13 }
14
15 /// Ensure that we do not just pick the topmost possible item on int2ptr casts.
16 fn example(variant: bool) {
17     unsafe {
18         fn not_so_innocent(x: &mut u32) -> usize {
19             let x_raw4 = x as *mut u32;
20             x_raw4.expose_addr()
21         }
22
23         let mut c = 42u32;
24
25         let x_unique1 = &mut c;
26         // [..., Unique(1)]
27
28         let x_raw2 = x_unique1 as *mut u32;
29         let x_raw2_addr = x_raw2.expose_addr();
30         // [..., Unique(1), SharedRW(2)]
31
32         let x_unique3 = &mut *x_raw2;
33         // [.., Unique(1), SharedRW(2), Unique(3)]
34
35         assert_eq!(not_so_innocent(x_unique3), x_raw2_addr);
36         // [.., Unique(1), SharedRW(2), Unique(3), ..., SharedRW(4)]
37
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);
43
44         if variant {
45             // If we picked 2, this will invalidate 3.
46             *x_wildcard = 10;
47             // Now we use 3. Only possible if above we picked 4.
48             *x_unique3 = 12;
49         } else {
50             // This invalidates tag 4.
51             *x_unique3 = 10;
52             // Now try to write with the "guessed" tag; it must be 2.
53             *x_wildcard = 12;
54         }
55     }
56 }
57
58 fn test() {
59     unsafe {
60         let root = &mut 42;
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);
67         // First use child.
68         *(addr2 as *mut i32) -= 2; // picks child_raw
69         *child -= 2;
70         // Then use root.
71         *(addr1 as *mut i32) += 2; // picks root_raw
72         *root += 2;
73         // Value should be unchanged.
74         assert_eq!(*root, 42);
75     }
76 }
77
78 fn main() {
79     ref_raw_int_raw();
80     example(false);
81     example(true);
82     test();
83 }