]>
Commit | Line | Data |
---|---|---|
416331ca | 1 | // run-pass |
1a4d82fc JJ |
2 | // alloc::heap::reallocate test. |
3 | // | |
4 | // Ideally this would be revised to use no_std, but for now it serves | |
5 | // well enough to reproduce (and illustrate) the bug from #16687. | |
6 | ||
b7449926 | 7 | #![feature(allocator_api)] |
3dfed10e | 8 | #![feature(slice_ptr_get)] |
c34b1796 | 9 | |
fc512014 | 10 | use std::alloc::{handle_alloc_error, Allocator, Global, Layout}; |
83c7162d | 11 | use std::ptr::{self, NonNull}; |
1a4d82fc JJ |
12 | |
13 | fn main() { | |
14 | unsafe { | |
15 | assert!(test_triangle()); | |
16 | } | |
17 | } | |
18 | ||
19 | unsafe fn test_triangle() -> bool { | |
ba9703b0 | 20 | static COUNT: usize = 16; |
c1a9b12d | 21 | let mut ascend = vec![ptr::null_mut(); COUNT]; |
85aaf69f | 22 | let ascend = &mut *ascend; |
ba9703b0 | 23 | static ALIGN: usize = 1; |
1a4d82fc JJ |
24 | |
25 | // Checks that `ascend` forms triangle of ascending size formed | |
26 | // from pairs of rows (where each pair of rows is equally sized), | |
27 | // and the elements of the triangle match their row-pair index. | |
28 | unsafe fn sanity_check(ascend: &[*mut u8]) { | |
c34b1796 | 29 | for i in 0..COUNT / 2 { |
ba9703b0 | 30 | let (p0, p1, size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); |
c34b1796 | 31 | for j in 0..size { |
b7449926 XL |
32 | assert_eq!(*p0.add(j), i as u8); |
33 | assert_eq!(*p1.add(j), i as u8); | |
1a4d82fc JJ |
34 | } |
35 | } | |
36 | } | |
37 | ||
ba9703b0 | 38 | static PRINT: bool = false; |
1a4d82fc | 39 | |
041b39d2 XL |
40 | unsafe fn allocate(layout: Layout) -> *mut u8 { |
41 | if PRINT { | |
42 | println!("allocate({:?})", layout); | |
43 | } | |
1a4d82fc | 44 | |
fc512014 | 45 | let ptr = Global.allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); |
1a4d82fc | 46 | |
041b39d2 | 47 | if PRINT { |
3dfed10e | 48 | println!("allocate({:?}) = {:?}", layout, ptr); |
1a4d82fc JJ |
49 | } |
50 | ||
1b1a35ee | 51 | ptr.as_mut_ptr() |
1a4d82fc | 52 | } |
041b39d2 XL |
53 | |
54 | unsafe fn deallocate(ptr: *mut u8, layout: Layout) { | |
55 | if PRINT { | |
56 | println!("deallocate({:?}, {:?}", ptr, layout); | |
1a4d82fc JJ |
57 | } |
58 | ||
fc512014 | 59 | Global.deallocate(NonNull::new_unchecked(ptr), layout); |
1a4d82fc | 60 | } |
041b39d2 XL |
61 | |
62 | unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 { | |
1a4d82fc | 63 | if PRINT { |
041b39d2 | 64 | println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new); |
1a4d82fc JJ |
65 | } |
66 | ||
ba9703b0 | 67 | let memory = if new.size() > old.size() { |
1b1a35ee | 68 | Global.grow(NonNull::new_unchecked(ptr), old, new) |
ba9703b0 | 69 | } else { |
1b1a35ee | 70 | Global.shrink(NonNull::new_unchecked(ptr), old, new) |
ba9703b0 XL |
71 | }; |
72 | ||
1b1a35ee | 73 | let ptr = memory.unwrap_or_else(|_| handle_alloc_error(new)); |
1a4d82fc JJ |
74 | |
75 | if PRINT { | |
3dfed10e | 76 | println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", ptr, old, new, ptr); |
1a4d82fc | 77 | } |
1b1a35ee | 78 | ptr.as_mut_ptr() |
1a4d82fc JJ |
79 | } |
80 | ||
ba9703b0 XL |
81 | fn idx_to_size(i: usize) -> usize { |
82 | (i + 1) * 10 | |
83 | } | |
1a4d82fc JJ |
84 | |
85 | // Allocate pairs of rows that form a triangle shape. (Hope is | |
86 | // that at least two rows will be allocated near each other, so | |
87 | // that we trigger the bug (a buffer overrun) in an observable | |
88 | // way.) | |
c34b1796 | 89 | for i in 0..COUNT / 2 { |
1a4d82fc | 90 | let size = idx_to_size(i); |
ba9703b0 XL |
91 | ascend[2 * i] = allocate(Layout::from_size_align(size, ALIGN).unwrap()); |
92 | ascend[2 * i + 1] = allocate(Layout::from_size_align(size, ALIGN).unwrap()); | |
1a4d82fc JJ |
93 | } |
94 | ||
95 | // Initialize each pair of rows to distinct value. | |
c34b1796 | 96 | for i in 0..COUNT / 2 { |
ba9703b0 | 97 | let (p0, p1, size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); |
85aaf69f | 98 | for j in 0..size { |
b7449926 XL |
99 | *p0.add(j) = i as u8; |
100 | *p1.add(j) = i as u8; | |
1a4d82fc JJ |
101 | } |
102 | } | |
103 | ||
85aaf69f | 104 | sanity_check(&*ascend); |
1a4d82fc JJ |
105 | test_1(ascend); // triangle -> square |
106 | test_2(ascend); // square -> triangle | |
107 | test_3(ascend); // triangle -> square | |
108 | test_4(ascend); // square -> triangle | |
109 | ||
c34b1796 | 110 | for i in 0..COUNT / 2 { |
1a4d82fc | 111 | let size = idx_to_size(i); |
ba9703b0 XL |
112 | deallocate(ascend[2 * i], Layout::from_size_align(size, ALIGN).unwrap()); |
113 | deallocate(ascend[2 * i + 1], Layout::from_size_align(size, ALIGN).unwrap()); | |
1a4d82fc JJ |
114 | } |
115 | ||
116 | return true; | |
117 | ||
118 | // Test 1: turn the triangle into a square (in terms of | |
119 | // allocation; initialized portion remains a triangle) by | |
120 | // realloc'ing each row from top to bottom, and checking all the | |
121 | // rows as we go. | |
122 | unsafe fn test_1(ascend: &mut [*mut u8]) { | |
ba9703b0 | 123 | let new_size = idx_to_size(COUNT - 1); |
041b39d2 | 124 | let new = Layout::from_size_align(new_size, ALIGN).unwrap(); |
c34b1796 | 125 | for i in 0..COUNT / 2 { |
ba9703b0 | 126 | let (p0, p1, old_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); |
1a4d82fc | 127 | assert!(old_size < new_size); |
041b39d2 | 128 | let old = Layout::from_size_align(old_size, ALIGN).unwrap(); |
1a4d82fc | 129 | |
ba9703b0 | 130 | ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); |
85aaf69f | 131 | sanity_check(&*ascend); |
1a4d82fc | 132 | |
ba9703b0 | 133 | ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); |
85aaf69f | 134 | sanity_check(&*ascend); |
1a4d82fc JJ |
135 | } |
136 | } | |
137 | ||
138 | // Test 2: turn the square back into a triangle, top to bottom. | |
139 | unsafe fn test_2(ascend: &mut [*mut u8]) { | |
ba9703b0 | 140 | let old_size = idx_to_size(COUNT - 1); |
041b39d2 | 141 | let old = Layout::from_size_align(old_size, ALIGN).unwrap(); |
c34b1796 | 142 | for i in 0..COUNT / 2 { |
ba9703b0 | 143 | let (p0, p1, new_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); |
1a4d82fc | 144 | assert!(new_size < old_size); |
041b39d2 | 145 | let new = Layout::from_size_align(new_size, ALIGN).unwrap(); |
1a4d82fc | 146 | |
ba9703b0 | 147 | ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); |
85aaf69f | 148 | sanity_check(&*ascend); |
1a4d82fc | 149 | |
ba9703b0 | 150 | ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); |
85aaf69f | 151 | sanity_check(&*ascend); |
1a4d82fc JJ |
152 | } |
153 | } | |
154 | ||
155 | // Test 3: turn triangle into a square, bottom to top. | |
156 | unsafe fn test_3(ascend: &mut [*mut u8]) { | |
ba9703b0 | 157 | let new_size = idx_to_size(COUNT - 1); |
041b39d2 | 158 | let new = Layout::from_size_align(new_size, ALIGN).unwrap(); |
c34b1796 | 159 | for i in (0..COUNT / 2).rev() { |
ba9703b0 | 160 | let (p0, p1, old_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); |
1a4d82fc | 161 | assert!(old_size < new_size); |
041b39d2 | 162 | let old = Layout::from_size_align(old_size, ALIGN).unwrap(); |
1a4d82fc | 163 | |
ba9703b0 | 164 | ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); |
85aaf69f | 165 | sanity_check(&*ascend); |
1a4d82fc | 166 | |
ba9703b0 | 167 | ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); |
85aaf69f | 168 | sanity_check(&*ascend); |
1a4d82fc JJ |
169 | } |
170 | } | |
171 | ||
172 | // Test 4: turn the square back into a triangle, bottom to top. | |
173 | unsafe fn test_4(ascend: &mut [*mut u8]) { | |
ba9703b0 | 174 | let old_size = idx_to_size(COUNT - 1); |
041b39d2 | 175 | let old = Layout::from_size_align(old_size, ALIGN).unwrap(); |
c34b1796 | 176 | for i in (0..COUNT / 2).rev() { |
ba9703b0 | 177 | let (p0, p1, new_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); |
1a4d82fc | 178 | assert!(new_size < old_size); |
041b39d2 | 179 | let new = Layout::from_size_align(new_size, ALIGN).unwrap(); |
1a4d82fc | 180 | |
ba9703b0 | 181 | ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); |
85aaf69f | 182 | sanity_check(&*ascend); |
1a4d82fc | 183 | |
ba9703b0 | 184 | ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); |
85aaf69f | 185 | sanity_check(&*ascend); |
1a4d82fc JJ |
186 | } |
187 | } | |
188 | } |