Ensure ArenaRef
pointers are aligned to their contained type (#4002)
We think this may fix a segfault that sometimes occurs during `display_layer`.
This commit is contained in:
commit
02ef6fc973
1 changed files with 45 additions and 5 deletions
|
@ -66,18 +66,19 @@ impl Arena {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let layout = alloc::Layout::new::<T>().pad_to_align();
|
||||
let next_offset = self.offset.add(layout.size());
|
||||
assert!(next_offset <= self.end);
|
||||
let layout = alloc::Layout::new::<T>();
|
||||
let offset = self.offset.add(self.offset.align_offset(layout.align()));
|
||||
let next_offset = offset.add(layout.size());
|
||||
assert!(next_offset <= self.end, "not enough space in Arena");
|
||||
|
||||
let result = ArenaBox {
|
||||
ptr: self.offset.cast(),
|
||||
ptr: offset.cast(),
|
||||
valid: self.valid.clone(),
|
||||
};
|
||||
|
||||
inner_writer(result.ptr, f);
|
||||
self.elements.push(ArenaElement {
|
||||
value: self.offset,
|
||||
value: offset,
|
||||
drop: drop::<T>,
|
||||
});
|
||||
self.offset = next_offset;
|
||||
|
@ -199,4 +200,43 @@ mod tests {
|
|||
arena.clear();
|
||||
assert!(dropped.get());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "not enough space in Arena")]
|
||||
fn test_arena_overflow() {
|
||||
let mut arena = Arena::new(16);
|
||||
arena.alloc(|| 1u64);
|
||||
arena.alloc(|| 2u64);
|
||||
// This should panic.
|
||||
arena.alloc(|| 3u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arena_alignment() {
|
||||
let mut arena = Arena::new(256);
|
||||
let x1 = arena.alloc(|| 1u8);
|
||||
let x2 = arena.alloc(|| 2u16);
|
||||
let x3 = arena.alloc(|| 3u32);
|
||||
let x4 = arena.alloc(|| 4u64);
|
||||
let x5 = arena.alloc(|| 5u64);
|
||||
|
||||
assert_eq!(*x1, 1);
|
||||
assert_eq!(*x2, 2);
|
||||
assert_eq!(*x3, 3);
|
||||
assert_eq!(*x4, 4);
|
||||
assert_eq!(*x5, 5);
|
||||
|
||||
assert_eq!(x1.ptr.align_offset(std::mem::align_of_val(&*x1)), 0);
|
||||
assert_eq!(x2.ptr.align_offset(std::mem::align_of_val(&*x2)), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "attempted to dereference an ArenaRef after its Arena was cleared")]
|
||||
fn test_arena_use_after_clear() {
|
||||
let mut arena = Arena::new(16);
|
||||
let value = arena.alloc(|| 1u64);
|
||||
|
||||
arena.clear();
|
||||
let _read_value = *value;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue