]> Repositorios git - scryer-prolog.git/commitdiff
check whether (re-)allocation succeeded
authorBennet Bleßmann <[email protected]>
Sun, 11 Aug 2024 17:19:00 +0000 (19:19 +0200)
committerBennet Bleßmann <[email protected]>
Sun, 11 Aug 2024 17:20:33 +0000 (19:20 +0200)
fixes mthom/scryer-prolog#2449

src/ffi.rs
src/machine/stack.rs
src/raw_block.rs

index 04e85ab3cf782151f1526efa69616ad5c6f94e8d..a3e933800adda8fb89fda716aa9a68db1cefa4d5 100644 (file)
@@ -21,7 +21,7 @@ and finally we add the pointer the size of what we've written.
 
 use crate::atom_table::Atom;
 
-use std::alloc::{alloc, Layout};
+use std::alloc::{self, Layout};
 use std::any::Any;
 use std::collections::HashMap;
 use std::convert::TryFrom;
@@ -223,42 +223,47 @@ impl ForeignFunctionTable {
         arg: &mut Value,
         structs_table: &mut HashMap<String, StructImpl>,
     ) -> Result<(Box<dyn Any>, usize, usize), FFIError> {
-        unsafe {
-            match arg {
-                Value::Struct(ref name, ref mut struct_args) => {
-                    if let Some(ref mut struct_type) = structs_table.clone().get_mut(name) {
-                        let layout = Layout::from_size_align(
-                            struct_type.ffi_type.size,
-                            struct_type.ffi_type.alignment.into(),
-                        )
-                        .unwrap();
-                        let align = struct_type.ffi_type.alignment as usize;
-                        let size = struct_type.ffi_type.size;
-                        let ptr = alloc(layout) as *mut c_void;
-                        let mut field_ptr = ptr;
-
-                        #[allow(clippy::needless_range_loop)]
-                        for i in 0..(struct_type.fields.len() - 1) {
-                            macro_rules! try_write_int {
-                                ($type:ty) => {{
-                                    field_ptr = field_ptr
-                                        .add(field_ptr.align_offset(std::mem::align_of::<$type>()));
-                                    let n: $type = <$type>::try_from(struct_args[i].as_int()?)
-                                        .map_err(|_| FFIError::ValueDontFit)?;
-                                    std::ptr::write(field_ptr as *mut $type, n);
-                                    field_ptr = field_ptr.add(std::mem::size_of::<$type>());
-                                }};
-                            }
+        match arg {
+            Value::Struct(ref name, ref mut struct_args) => {
+                if let Some(ref mut struct_type) = structs_table.clone().get_mut(name) {
+                    let layout = Layout::from_size_align(
+                        struct_type.ffi_type.size,
+                        struct_type.ffi_type.alignment.into(),
+                    )
+                    .unwrap();
+                    let align = struct_type.ffi_type.alignment as usize;
+                    let size = struct_type.ffi_type.size;
+                    let ptr = unsafe { alloc::alloc(layout) as *mut c_void };
 
-                            macro_rules! write {
-                                ($type:ty, $value:expr) => {{
-                                    let data: $type = $value;
-                                    std::ptr::write(field_ptr as *mut $type, data);
-                                    field_ptr = field_ptr.add(align);
-                                }};
-                            }
+                    if ptr.is_null() {
+                        panic!("allocation failed")
+                    }
 
-                            let field = struct_type.fields[i];
+                    let mut field_ptr = ptr;
+
+                    #[allow(clippy::needless_range_loop)]
+                    for i in 0..(struct_type.fields.len() - 1) {
+                        macro_rules! try_write_int {
+                            ($type:ty) => {{
+                                field_ptr = field_ptr
+                                    .add(field_ptr.align_offset(std::mem::align_of::<$type>()));
+                                let n: $type = <$type>::try_from(struct_args[i].as_int()?)
+                                    .map_err(|_| FFIError::ValueDontFit)?;
+                                std::ptr::write(field_ptr as *mut $type, n);
+                                field_ptr = field_ptr.add(std::mem::size_of::<$type>());
+                            }};
+                        }
+
+                        macro_rules! write {
+                            ($type:ty, $value:expr) => {{
+                                let data: $type = $value;
+                                std::ptr::write(field_ptr as *mut $type, data);
+                                field_ptr = field_ptr.add(align);
+                            }};
+                        }
+
+                        let field = struct_type.fields[i];
+                        unsafe {
                             match (*field).type_ as u32 {
                                 libffi::raw::FFI_TYPE_UINT8 => try_write_int!(u8),
                                 libffi::raw::FFI_TYPE_SINT8 => try_write_int!(i8),
@@ -294,14 +299,15 @@ impl ForeignFunctionTable {
                                 }
                             }
                         }
-                        #[allow(clippy::from_raw_with_void_ptr)]
-                        Ok((Box::from_raw(ptr), size, align))
-                    } else {
-                        Err(FFIError::InvalidStructName)
                     }
+
+                    #[allow(clippy::from_raw_with_void_ptr)]
+                    Ok((unsafe { Box::from_raw(ptr) }, size, align))
+                } else {
+                    Err(FFIError::InvalidStructName)
                 }
-                _ => Err(FFIError::ValueCast),
             }
+            _ => Err(FFIError::ValueCast),
         }
     }
 
@@ -377,7 +383,11 @@ impl ForeignFunctionTable {
                         struct_type.ffi_type.alignment.into(),
                     )
                     .unwrap();
-                    let ptr = alloc(layout) as *mut c_void;
+                    let ptr = alloc::alloc(layout) as *mut c_void;
+
+                    if ptr.is_null() {
+                        panic!("allocation failed")
+                    }
 
                     libffi::raw::ffi_call(
                         &mut function_impl.cif,
index 7f35cdbc6fb472e6a7ef51666ffcad61200c1614..210a7cac48259b1c6044873ac6740850845ee5e5 100644 (file)
@@ -174,7 +174,9 @@ impl Stack {
             let ptr = self.buf.alloc(frame_size);
 
             if ptr.is_null() {
-                self.buf.grow();
+                if !self.buf.grow() {
+                    panic!("growing the stack failed")
+                }
             } else {
                 return ptr;
             }
index 0c27bddef3cca1d4b3a433c6905da71ff30c7312..8282a94d32a0b82f274a5f0513cb6f13044e7f01 100644 (file)
@@ -41,22 +41,32 @@ impl<T: RawBlockTraits> RawBlock<T> {
 
     unsafe fn init_at_size(&mut self, cap: usize) {
         let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());
-
-        self.base = alloc::alloc(layout) as *const _;
+        let new_base = alloc::alloc(layout).cast_const();
+        if new_base.is_null() {
+            panic!("failed to allocate for init_at_size");
+        }
+        self.base = new_base;
         self.top = self.base.add(cap);
-        *self.ptr.get_mut() = self.base as *mut _;
+        *self.ptr.get_mut() = self.base.cast_mut();
     }
 
-    pub unsafe fn grow(&mut self) {
+    pub unsafe fn grow(&mut self) -> bool {
         if self.base.is_null() {
             self.init_at_size(T::init_size());
+            true
         } else {
             let size = self.size();
             let layout = alloc::Layout::from_size_align_unchecked(size, T::align());
 
-            self.base = alloc::realloc(self.base as *mut _, layout, size * 2) as *const _;
-            self.top = (self.base as usize + size * 2) as *const _;
-            *self.ptr.get_mut() = (self.base as usize + size) as *mut _;
+            let new_base = alloc::realloc(self.base.cast_mut(), layout, size * 2).cast_const();
+            if new_base.is_null() {
+                false
+            } else {
+                self.base = new_base;
+                self.top = (self.base as usize + size * 2) as *const _;
+                *self.ptr.get_mut() = (self.base as usize + size) as *mut _;
+                true
+            }
         }
     }