Skip to content

Commit 7a03f75

Browse files
committed
Hunt down UB
1 parent 23ae87d commit 7a03f75

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

src/hole.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,14 @@ impl HoleList {
9696
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<(NonNull<u8>, Layout), ()> {
9797
let aligned_layout = Self::align_layout(layout);
9898

99-
allocate_first_fit(&mut self.first, aligned_layout).map(|holeinfo| {
100-
(
101-
NonNull::new(holeinfo.addr as *mut u8).unwrap(),
102-
aligned_layout,
103-
)
104-
})
99+
let _ = allocate_first_fit(&mut self.first, aligned_layout);
100+
// .map(|holeinfo| {
101+
// (
102+
// NonNull::new(holeinfo.addr).unwrap(),
103+
// aligned_layout,
104+
// )
105+
// })
106+
Err(())
105107
}
106108

107109
/// Frees the allocation given by `ptr` and `layout`.
@@ -147,7 +149,7 @@ impl Hole {
147149
/// Returns basic information about the hole.
148150
fn info(&mut self) -> HoleInfo {
149151
HoleInfo {
150-
addr: self as *mut _ as *mut u8,
152+
addr: self as *mut Hole,
151153
size: self.size,
152154
}
153155
}
@@ -156,10 +158,16 @@ impl Hole {
156158
/// Basic information about a hole.
157159
#[derive(Debug, Clone, Copy)]
158160
struct HoleInfo {
159-
addr: *mut u8,
161+
addr: *mut Hole,
160162
size: usize,
161163
}
162164

165+
impl HoleInfo {
166+
pub fn addr_u8(&self) -> *mut u8 {
167+
self.addr.cast()
168+
}
169+
}
170+
163171
/// The result returned by `split_hole` and `allocate_first_fit`. Contains the address and size of
164172
/// the allocation (in the `info` field), and the front and back padding.
165173
struct Allocation {
@@ -177,17 +185,17 @@ fn split_hole(hole: HoleInfo, required_layout: Layout) -> Option<Allocation> {
177185
let required_size = required_layout.size();
178186
let required_align = required_layout.align();
179187

180-
let (aligned_addr, front_padding) = if hole.addr == align_up(hole.addr, required_align) {
188+
let (aligned_addr, front_padding) = if hole.addr_u8() == align_up(hole.addr_u8(), required_align) {
181189
// hole has already the required alignment
182190
(hole.addr, None)
183191
} else {
184192
// the required alignment causes some padding before the allocation
185-
let aligned_addr = align_up(hole.addr.wrapping_add(HoleList::min_size()), required_align);
193+
let aligned_addr = align_up(hole.addr_u8().wrapping_add(HoleList::min_size()), required_align).cast::<Hole>();
186194
(
187195
aligned_addr,
188196
Some(HoleInfo {
189197
addr: hole.addr,
190-
size: unsafe { aligned_addr.offset_from(hole.addr) }
198+
size: unsafe { aligned_addr.cast::<u8>().offset_from(hole.addr_u8()) }
191199
.try_into()
192200
.unwrap(),
193201
}),
@@ -253,9 +261,23 @@ fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<HoleInf
253261
// previous - front_padding
254262
// front_padding - back_padding
255263
// back_padding - previous.next
256-
previous.next = previous.next.as_mut().unwrap().next.take();
264+
let prev = previous as *mut Hole as usize;
265+
println!("prev: {:016X}..{:016X}", prev, prev + previous.size);
266+
if let Some(padding) = allocation.back_padding {
267+
let back = padding.addr as usize;
268+
println!("back: {:016X}..{:016X}", back, back + padding.size);
269+
}
270+
if let Some(next) = previous.next.as_mut() {
271+
let nxt = (*next) as *mut Hole as usize;
272+
println!("next: {:016X}..{:016X}", nxt, nxt + next.size);
273+
}
274+
panic!();
275+
276+
let new_next = previous.next.as_mut().unwrap().next.take();
277+
278+
previous.next = new_next;
257279
if let Some(padding) = allocation.front_padding {
258-
let ptr = padding.addr as *mut Hole;
280+
let ptr = padding.addr;
259281
unsafe {
260282
ptr.write(Hole {
261283
size: padding.size,
@@ -266,7 +288,7 @@ fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<HoleInf
266288
previous = move_helper(previous).next.as_mut().unwrap();
267289
}
268290
if let Some(padding) = allocation.back_padding {
269-
let ptr = padding.addr as *mut Hole;
291+
let ptr = padding.addr;
270292
unsafe {
271293
ptr.write(Hole {
272294
size: padding.size,
@@ -318,7 +340,7 @@ fn deallocate(mut hole: &mut Hole, addr: *mut u8, mut size: usize) {
318340
match next_hole_info {
319341
Some(next)
320342
if hole_addr.wrapping_offset(hole.size.try_into().unwrap()) == addr
321-
&& addr.wrapping_offset(size.try_into().unwrap()) == next.addr =>
343+
&& addr.wrapping_offset(size.try_into().unwrap()) == next.addr_u8() =>
322344
{
323345
// block fills the gap between this hole and the next hole
324346
// before: ___XXX____YYYYY____ where X is this hole and Y the next hole
@@ -338,7 +360,7 @@ fn deallocate(mut hole: &mut Hole, addr: *mut u8, mut size: usize) {
338360

339361
hole.size += size; // merge the F block to this X block
340362
}
341-
Some(next) if addr.wrapping_offset(size.try_into().unwrap()) == next.addr => {
363+
Some(next) if addr.wrapping_offset(size.try_into().unwrap()) == next.addr_u8() => {
342364
// block is right before the next hole but there is used memory before it
343365
// before: ___XXX______YYYYY____ where X is this hole and Y the next hole
344366
// after: ___XXX__FFFFYYYYY____ where F is the freed block
@@ -347,7 +369,7 @@ fn deallocate(mut hole: &mut Hole, addr: *mut u8, mut size: usize) {
347369
size += next.size; // free the merged F/Y block in next iteration
348370
continue;
349371
}
350-
Some(next) if next.addr <= addr => {
372+
Some(next) if next.addr_u8() <= addr => {
351373
// block is behind the next hole, so we delegate it to the next hole
352374
// before: ___XXX__YYYYY________ where X is this hole and Y the next hole
353375
// after: ___XXX__YYYYY__FFFF__ where F is the freed block

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
)]
66
#![no_std]
77

8-
#[cfg(test)]
8+
// #[cfg(test)]
99
#[macro_use]
1010
extern crate std;
1111

src/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ fn align_from_small_to_big() {
253253

254254
// allocate 28 bytes so that the heap end is only 4 byte aligned
255255
assert!(heap.allocate_first_fit(layout_1.clone()).is_ok());
256-
// try to allocate a 8 byte aligned block
257-
assert!(heap.allocate_first_fit(layout_2.clone()).is_ok());
256+
// // try to allocate a 8 byte aligned block
257+
// assert!(heap.allocate_first_fit(layout_2.clone()).is_ok());
258258
}
259259

260260
#[test]

0 commit comments

Comments
 (0)