]> git.proxmox.com Git - rustc.git/blame - src/test/ui/realloc-16687.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / src / test / ui / realloc-16687.rs
CommitLineData
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 10use std::alloc::{handle_alloc_error, Allocator, Global, Layout};
83c7162d 11use std::ptr::{self, NonNull};
1a4d82fc
JJ
12
13fn main() {
14 unsafe {
15 assert!(test_triangle());
16 }
17}
18
19unsafe 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}