From: Bennet Bleßmann Date: Sun, 7 Jul 2024 13:51:22 +0000 (+0200) Subject: fix leak of slaps with dropped payload X-Git-Tag: v0.10.0~127^2 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=5d03be4b092e113d5bc420aa83704bd7d6be075e;p=scryer-prolog.git fix leak of slaps with dropped payload --- diff --git a/src/arena.rs b/src/arena.rs index 46d4d26a..a3449d44 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -197,6 +197,7 @@ pub enum ArenaHeaderTag { } #[bitfield] +#[repr(align(8))] #[derive(Copy, Clone, Debug)] pub struct ArenaHeader { #[allow(dead_code)] @@ -590,7 +591,16 @@ impl ArenaAllocated for LiveLoadState { unsafe fn dealloc(ptr: NonNull>) { let mut slab = unsafe { Box::from_raw(ptr.as_ptr()) }; - unsafe { ManuallyDrop::drop(&mut slab.payload) }; + + match slab.tag() { + ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => { + unsafe { ManuallyDrop::drop(&mut slab.payload) }; + } + ArenaHeaderTag::Dropped => {} + _ => { + unreachable!() + } + } drop(slab); } } @@ -710,6 +720,7 @@ impl IndexPtrSlab { let untyped_arena = UntypedArenaSlab { // safety: pointer from Box::into_raw is never null slab: unsafe { NonNull::new_unchecked(raw_box.cast::()) }, + tag: ::tag(), }; (allocated_ptr, untyped_arena) @@ -747,20 +758,21 @@ impl TypedAllocSlab { UntypedArenaSlab { // safety: pointer from Box::into_raw is never null slab: unsafe { NonNull::new_unchecked(raw_box.cast::()) }, + tag: T::tag(), }, ) } } #[derive(Debug)] -#[repr(transparent)] pub struct UntypedArenaSlab { slab: NonNull, + tag: ArenaHeaderTag, } impl Drop for UntypedArenaSlab { fn drop(&mut self) { - unsafe { drop_slab_in_place(self.slab) }; + unsafe { drop_slab_in_place(self.slab, self.tag) }; } } @@ -784,14 +796,14 @@ impl Arena { } } -unsafe fn drop_slab_in_place(value: NonNull) { +unsafe fn drop_slab_in_place(value: NonNull, tag: ArenaHeaderTag) { macro_rules! drop_typed_slab_in_place { ($payload: ty, $value: expr) => { <$payload as ArenaAllocated>::dealloc($value.cast::>()) }; } - match (unsafe { value.as_ref() }).header.tag() { + match tag { ArenaHeaderTag::Integer => { drop_typed_slab_in_place!(Integer, value); } diff --git a/src/machine/streams.rs b/src/machine/streams.rs index b6281933..d7df644d 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -470,7 +470,16 @@ macro_rules! arena_allocated_impl_for_stream { unsafe fn dealloc(ptr: std::ptr::NonNull>) { let mut slab = unsafe { Box::from_raw(ptr.as_ptr()) }; - unsafe { std::mem::ManuallyDrop::drop(slab.payload()) }; + + match slab.tag() { + ArenaHeaderTag::$stream_tag => { + unsafe { std::mem::ManuallyDrop::drop(slab.payload()) }; + } + ArenaHeaderTag::Dropped => {} + _ => { + unreachable!() + } + } drop(slab); } }