]> Repositorios git - scryer-prolog.git/commitdiff
fix leak of slaps with dropped payload
authorBennet Bleßmann <[email protected]>
Sun, 7 Jul 2024 13:51:22 +0000 (15:51 +0200)
committerBennet Bleßmann <[email protected]>
Sun, 7 Jul 2024 17:22:46 +0000 (19:22 +0200)
src/arena.rs
src/machine/streams.rs

index 46d4d26a8f623a5ea23c8e911bc08d759f427a47..a3449d44b904ed04e145fdcf37e2783244649abd 100644 (file)
@@ -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<TypedAllocSlab<Self>>) {
         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::<AllocSlab>()) },
+            tag: <IndexPtr as ArenaAllocated>::tag(),
         };
 
         (allocated_ptr, untyped_arena)
@@ -747,20 +758,21 @@ impl<T: ?Sized + ArenaAllocated> TypedAllocSlab<T> {
             UntypedArenaSlab {
                 // safety: pointer from Box::into_raw is never null
                 slab: unsafe { NonNull::new_unchecked(raw_box.cast::<AllocSlab>()) },
+                tag: T::tag(),
             },
         )
     }
 }
 
 #[derive(Debug)]
-#[repr(transparent)]
 pub struct UntypedArenaSlab {
     slab: NonNull<AllocSlab>,
+    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<AllocSlab>) {
+unsafe fn drop_slab_in_place(value: NonNull<AllocSlab>, tag: ArenaHeaderTag) {
     macro_rules! drop_typed_slab_in_place {
         ($payload: ty, $value: expr) => {
             <$payload as ArenaAllocated>::dealloc($value.cast::<TypedAllocSlab<$payload>>())
         };
     }
 
-    match (unsafe { value.as_ref() }).header.tag() {
+    match tag {
         ArenaHeaderTag::Integer => {
             drop_typed_slab_in_place!(Integer, value);
         }
index b6281933f97c992b4a380ccee07552a2729ecf1c..d7df644d0cdc17ff3267497ffb285037a444df81 100644 (file)
@@ -470,7 +470,16 @@ macro_rules! arena_allocated_impl_for_stream {
 
             unsafe fn dealloc(ptr: std::ptr::NonNull<TypedAllocSlab<Self>>) {
                 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);
             }
         }