|
| 1 | +// compile-flags: -Zmiri-seed= |
1 | 2 | #![feature(allocator_api)]
|
2 | 3 |
|
3 | 4 | use std::ptr::NonNull;
|
4 | 5 | use std::alloc::{Global, Alloc, Layout, System};
|
5 | 6 | use std::slice;
|
6 | 7 |
|
7 | 8 | fn check_alloc<T: Alloc>(mut allocator: T) { unsafe {
|
8 |
| - let layout = Layout::from_size_align(20, 4).unwrap(); |
9 |
| - let a = allocator.alloc(layout).unwrap(); |
10 |
| - allocator.dealloc(a, layout); |
| 9 | + for &align in &[4, 8, 16, 32] { |
| 10 | + let layout = Layout::from_size_align(20, align).unwrap(); |
11 | 11 |
|
12 |
| - let p1 = allocator.alloc_zeroed(layout).unwrap(); |
| 12 | + for _ in 0..32 { |
| 13 | + let a = allocator.alloc(layout).unwrap(); |
| 14 | + assert_eq!(a.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); |
| 15 | + allocator.dealloc(a, layout); |
| 16 | + } |
| 17 | + |
| 18 | + let p1 = allocator.alloc_zeroed(layout).unwrap(); |
| 19 | + assert_eq!(p1.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); |
13 | 20 |
|
14 |
| - let p2 = allocator.realloc(p1, Layout::from_size_align(20, 4).unwrap(), 40).unwrap(); |
15 |
| - let slice = slice::from_raw_parts(p2.as_ptr(), 20); |
16 |
| - assert_eq!(&slice, &[0_u8; 20]); |
| 21 | + let p2 = allocator.realloc(p1, layout, 40).unwrap(); |
| 22 | + let layout = Layout::from_size_align(40, align).unwrap(); |
| 23 | + assert_eq!(p2.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); |
| 24 | + let slice = slice::from_raw_parts(p2.as_ptr(), 20); |
| 25 | + assert_eq!(&slice, &[0_u8; 20]); |
17 | 26 |
|
18 |
| - // old size == new size |
19 |
| - let p3 = allocator.realloc(p2, Layout::from_size_align(40, 4).unwrap(), 40).unwrap(); |
20 |
| - let slice = slice::from_raw_parts(p3.as_ptr(), 20); |
21 |
| - assert_eq!(&slice, &[0_u8; 20]); |
| 27 | + // old size == new size |
| 28 | + let p3 = allocator.realloc(p2, layout, 40).unwrap(); |
| 29 | + assert_eq!(p3.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); |
| 30 | + let slice = slice::from_raw_parts(p3.as_ptr(), 20); |
| 31 | + assert_eq!(&slice, &[0_u8; 20]); |
22 | 32 |
|
23 |
| - // old size > new size |
24 |
| - let p4 = allocator.realloc(p3, Layout::from_size_align(40, 4).unwrap(), 10).unwrap(); |
25 |
| - let slice = slice::from_raw_parts(p4.as_ptr(), 10); |
26 |
| - assert_eq!(&slice, &[0_u8; 10]); |
| 33 | + // old size > new size |
| 34 | + let p4 = allocator.realloc(p3, layout, 10).unwrap(); |
| 35 | + let layout = Layout::from_size_align(10, align).unwrap(); |
| 36 | + assert_eq!(p4.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); |
| 37 | + let slice = slice::from_raw_parts(p4.as_ptr(), 10); |
| 38 | + assert_eq!(&slice, &[0_u8; 10]); |
27 | 39 |
|
28 |
| - allocator.dealloc(p4, Layout::from_size_align(10, 4).unwrap()); |
| 40 | + allocator.dealloc(p4, layout); |
| 41 | + } |
29 | 42 | } }
|
30 | 43 |
|
31 | 44 | fn check_overalign_requests<T: Alloc>(mut allocator: T) {
|
32 |
| - let size = 8; |
33 |
| - // Greater than `size`. |
34 |
| - let align = 16; |
35 |
| - // Miri is deterministic; no need to try many times. |
36 |
| - let iterations = 1; |
37 |
| - unsafe { |
38 |
| - let pointers: Vec<_> = (0..iterations).map(|_| { |
39 |
| - allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() |
40 |
| - }).collect(); |
41 |
| - for &ptr in &pointers { |
42 |
| - assert_eq!((ptr.as_ptr() as usize) % align, 0, |
43 |
| - "Got a pointer less aligned than requested") |
44 |
| - } |
| 45 | + for &size in &[2, 8, 64] { // size less than and bigger than alignment |
| 46 | + for &align in &[4, 8, 16, 32] { // Be sure to cover less than and bigger than `MIN_ALIGN` for all architectures |
| 47 | + let iterations = 32; |
| 48 | + unsafe { |
| 49 | + let pointers: Vec<_> = (0..iterations).map(|_| { |
| 50 | + allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() |
| 51 | + }).collect(); |
| 52 | + for &ptr in &pointers { |
| 53 | + assert_eq!((ptr.as_ptr() as usize) % align, 0, |
| 54 | + "Got a pointer less aligned than requested") |
| 55 | + } |
45 | 56 |
|
46 |
| - // Clean up. |
47 |
| - for &ptr in &pointers { |
48 |
| - allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) |
| 57 | + // Clean up. |
| 58 | + for &ptr in &pointers { |
| 59 | + allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) |
| 60 | + } |
| 61 | + } |
49 | 62 | }
|
50 | 63 | }
|
51 | 64 | }
|
@@ -75,7 +88,6 @@ fn box_to_global() {
|
75 | 88 | fn main() {
|
76 | 89 | check_alloc(System);
|
77 | 90 | check_alloc(Global);
|
78 |
| - #[cfg(not(target_os = "windows"))] // TODO: Inspects allocation base address on Windows; needs intptrcast model |
79 | 91 | check_overalign_requests(System);
|
80 | 92 | check_overalign_requests(Global);
|
81 | 93 | global_to_box();
|
|
0 commit comments