]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/tests/pass/heap_allocator.rs
Auto merge of #104915 - weihanglo:update-cargo, r=ehuss
[rust.git] / src / tools / miri / tests / pass / heap_allocator.rs
1 #![feature(allocator_api, slice_ptr_get)]
2
3 use std::alloc::{Allocator, Global, Layout, System};
4 use std::ptr::NonNull;
5 use std::slice;
6
7 fn check_alloc<T: Allocator>(allocator: T) {
8     unsafe {
9         for &align in &[4, 8, 16, 32] {
10             let layout_20 = Layout::from_size_align(20, align).unwrap();
11             let layout_40 = Layout::from_size_align(40, 4 * align).unwrap();
12             let layout_10 = Layout::from_size_align(10, align / 2).unwrap();
13
14             for _ in 0..32 {
15                 let a = allocator.allocate(layout_20).unwrap().as_non_null_ptr();
16                 assert_eq!(
17                     a.as_ptr() as usize % layout_20.align(),
18                     0,
19                     "pointer is incorrectly aligned",
20                 );
21                 allocator.deallocate(a, layout_20);
22             }
23
24             let p1 = allocator.allocate_zeroed(layout_20).unwrap().as_non_null_ptr();
25             assert_eq!(
26                 p1.as_ptr() as usize % layout_20.align(),
27                 0,
28                 "pointer is incorrectly aligned",
29             );
30             assert_eq!(*p1.as_ptr(), 0);
31
32             // old size < new size
33             let p2 = allocator.grow(p1, layout_20, layout_40).unwrap().as_non_null_ptr();
34             assert_eq!(
35                 p2.as_ptr() as usize % layout_40.align(),
36                 0,
37                 "pointer is incorrectly aligned",
38             );
39             let slice = slice::from_raw_parts(p2.as_ptr(), 20);
40             assert_eq!(&slice, &[0_u8; 20]);
41
42             // old size == new size
43             let p3 = allocator.grow(p2, layout_40, layout_40).unwrap().as_non_null_ptr();
44             assert_eq!(
45                 p3.as_ptr() as usize % layout_40.align(),
46                 0,
47                 "pointer is incorrectly aligned",
48             );
49             let slice = slice::from_raw_parts(p3.as_ptr(), 20);
50             assert_eq!(&slice, &[0_u8; 20]);
51
52             // old size > new size
53             let p4 = allocator.shrink(p3, layout_40, layout_10).unwrap().as_non_null_ptr();
54             assert_eq!(
55                 p4.as_ptr() as usize % layout_10.align(),
56                 0,
57                 "pointer is incorrectly aligned",
58             );
59             let slice = slice::from_raw_parts(p4.as_ptr(), 10);
60             assert_eq!(&slice, &[0_u8; 10]);
61
62             allocator.deallocate(p4, layout_10);
63         }
64     }
65 }
66
67 fn check_align_requests<T: Allocator>(allocator: T) {
68     #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/3255
69     for &size in &[2, 8, 64] { // size less than and bigger than alignment
70         for &align in &[4, 8, 16, 32] { // Be sure to cover less than and bigger than `MIN_ALIGN` for all architectures
71             let iterations = 32;
72             unsafe {
73                 let pointers: Vec<_> = (0..iterations)
74                     .map(|_| {
75                         allocator
76                             .allocate(Layout::from_size_align(size, align).unwrap())
77                             .unwrap()
78                             .as_non_null_ptr()
79                     })
80                     .collect();
81                 for &ptr in &pointers {
82                     assert_eq!(
83                         (ptr.as_ptr() as usize) % align,
84                         0,
85                         "Got a pointer less aligned than requested",
86                     )
87                 }
88
89                 // Clean up.
90                 for &ptr in &pointers {
91                     allocator.deallocate(ptr, Layout::from_size_align(size, align).unwrap())
92                 }
93             }
94         }
95     };
96 }
97
98 fn global_to_box() {
99     type T = [i32; 4];
100     let l = Layout::new::<T>();
101     // allocate manually with global allocator, then turn into Box and free there
102     unsafe {
103         let ptr = Global.allocate(l).unwrap().as_non_null_ptr().as_ptr() as *mut T;
104         let b = Box::from_raw(ptr);
105         drop(b);
106     }
107 }
108
109 fn box_to_global() {
110     type T = [i32; 4];
111     let l = Layout::new::<T>();
112     // allocate with the Box, then deallocate manually with global allocator
113     unsafe {
114         let b = Box::new(T::default());
115         let ptr = Box::into_raw(b);
116         Global.deallocate(NonNull::new(ptr as *mut u8).unwrap(), l);
117     }
118 }
119
120 fn main() {
121     check_alloc(System);
122     check_alloc(Global);
123     check_align_requests(System);
124     check_align_requests(Global);
125     global_to_box();
126     box_to_global();
127 }