about summary refs log tree commit diff
path: root/src/tools/miri/tests/pass/adjacent-allocs.rs
blob: 711c54fd68ad54b86ccb78fd333f738b27c900c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//@compile-flags: -Zmiri-permissive-provenance

fn ensure_allocs_can_be_adjacent() {
    for _ in 0..512 {
        let n = 0u64;
        let ptr: *const u64 = &n;
        let ptr2 = {
            let m = 0u64;
            &m as *const u64
        };
        if ptr.wrapping_add(1) == ptr2 {
            return;
        }
    }
    panic!("never saw adjacent stack variables?");
}

fn test1() {
    // The slack between allocations is random.
    // Loop a few times to hit the zero-slack case.
    for _ in 0..512 {
        let n = 0u64;
        let ptr: *const u64 = &n;

        // Allocate a new stack variable whose lifetime quickly ends.
        // If there's a chance that &m == ptr.add(1), then an int-to-ptr cast of
        // that value will have ambiguous provenance between n and m.
        // See https://github.com/rust-lang/miri/issues/1866#issuecomment-985770125
        {
            let m = 0u64;
            let _ptr = &m as *const u64;
        }

        let iptr = ptr as usize;
        let zst = (iptr + 8) as *const ();
        // This is a ZST ptr just at the end of `n`, so it should be valid to deref.
        unsafe { *zst }
    }
}

fn test2() {
    fn foo() -> u64 {
        0
    }

    for _ in 0..512 {
        let n = 0u64;
        let ptr: *const u64 = &n;
        foo();
        let iptr = ptr as usize;
        unsafe {
            let start = &*std::ptr::slice_from_raw_parts(iptr as *const (), 1);
            let end = &*std::ptr::slice_from_raw_parts((iptr + 8) as *const (), 1);
            assert_eq!(start.len(), end.len());
        }
    }
}

fn main() {
    ensure_allocs_can_be_adjacent();
    test1();
    test2();
}