]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/tests/pass/align_offset_symbolic.rs
Auto merge of #104915 - weihanglo:update-cargo, r=ehuss
[rust.git] / src / tools / miri / tests / pass / align_offset_symbolic.rs
1 //@compile-flags: -Zmiri-symbolic-alignment-check
2 #![feature(strict_provenance)]
3
4 use std::ptr;
5
6 fn test_align_offset() {
7     let d = Box::new([0u32; 4]);
8     // Get u8 pointer to base
9     let raw = d.as_ptr() as *const u8;
10
11     assert_eq!(raw.align_offset(2), 0);
12     assert_eq!(raw.align_offset(4), 0);
13     assert_eq!(raw.align_offset(8), usize::MAX); // requested alignment higher than allocation alignment
14
15     assert_eq!(raw.wrapping_offset(1).align_offset(2), 1);
16     assert_eq!(raw.wrapping_offset(1).align_offset(4), 3);
17     assert_eq!(raw.wrapping_offset(1).align_offset(8), usize::MAX); // requested alignment higher than allocation alignment
18
19     assert_eq!(raw.wrapping_offset(2).align_offset(2), 0);
20     assert_eq!(raw.wrapping_offset(2).align_offset(4), 2);
21     assert_eq!(raw.wrapping_offset(2).align_offset(8), usize::MAX); // requested alignment higher than allocation alignment
22
23     let p = ptr::invalid::<()>(1);
24     assert_eq!(p.align_offset(1), 0);
25 }
26
27 fn test_align_to() {
28     const N: usize = 4;
29     let d = Box::new([0u32; N]);
30     // Get u8 slice covering the entire thing
31     let s = unsafe { std::slice::from_raw_parts(d.as_ptr() as *const u8, 4 * N) };
32     let raw = s.as_ptr();
33
34     {
35         let (l, m, r) = unsafe { s.align_to::<u32>() };
36         assert_eq!(l.len(), 0);
37         assert_eq!(r.len(), 0);
38         assert_eq!(m.len(), N);
39         assert_eq!(raw, m.as_ptr() as *const u8);
40     }
41
42     {
43         let (l, m, r) = unsafe { s[1..].align_to::<u32>() };
44         assert_eq!(l.len(), 3);
45         assert_eq!(m.len(), N - 1);
46         assert_eq!(r.len(), 0);
47         assert_eq!(raw.wrapping_offset(4), m.as_ptr() as *const u8);
48     }
49
50     {
51         let (l, m, r) = unsafe { s[..4 * N - 1].align_to::<u32>() };
52         assert_eq!(l.len(), 0);
53         assert_eq!(m.len(), N - 1);
54         assert_eq!(r.len(), 3);
55         assert_eq!(raw, m.as_ptr() as *const u8);
56     }
57
58     {
59         let (l, m, r) = unsafe { s[1..4 * N - 1].align_to::<u32>() };
60         assert_eq!(l.len(), 3);
61         assert_eq!(m.len(), N - 2);
62         assert_eq!(r.len(), 3);
63         assert_eq!(raw.wrapping_offset(4), m.as_ptr() as *const u8);
64     }
65
66     {
67         #[repr(align(8))]
68         struct Align8(u64);
69
70         let (l, m, r) = unsafe { s.align_to::<Align8>() }; // requested alignment higher than allocation alignment
71         assert_eq!(l.len(), 4 * N);
72         assert_eq!(r.len(), 0);
73         assert_eq!(m.len(), 0);
74     }
75 }
76
77 fn test_from_utf8() {
78     const N: usize = 10;
79     let vec = vec![0x4141414141414141u64; N];
80     let content = unsafe { std::slice::from_raw_parts(vec.as_ptr() as *const u8, 8 * N) };
81     println!("{:?}", std::str::from_utf8(content).unwrap());
82 }
83
84 fn test_u64_array() {
85     #[derive(Default)]
86     #[repr(align(8))]
87     struct AlignToU64<T>(T);
88
89     const BYTE_LEN: usize = std::mem::size_of::<[u64; 4]>();
90     type Data = AlignToU64<[u8; BYTE_LEN]>;
91
92     fn example(data: &Data) {
93         let (head, u64_arrays, tail) = unsafe { data.0.align_to::<[u64; 4]>() };
94
95         assert!(head.is_empty(), "buffer was not aligned for 64-bit numbers");
96         assert_eq!(u64_arrays.len(), 1, "buffer was not long enough");
97         assert!(tail.is_empty(), "buffer was too long");
98
99         let u64_array = &u64_arrays[0];
100         let _val = u64_array[0]; // make sure we can actually load this
101     }
102
103     example(&Data::default());
104 }
105
106 fn main() {
107     test_align_offset();
108     test_align_to();
109     test_from_utf8();
110     test_u64_array();
111 }