fix crash when trying to load and ffi library with an invalid type specification

This commit is contained in:
Bennet Bleßmann
2025-01-21 23:37:47 +01:00
committed by Bennet Bleßmann
parent db3f2717bc
commit 34eab2e73a
3 changed files with 46 additions and 11 deletions

View File

@@ -80,8 +80,11 @@ impl ForeignFunctionTable {
self.table.extend(other.table);
}
pub fn define_struct(&mut self, name: &str, atom_fields: Vec<Atom>) {
let mut fields: Vec<_> = atom_fields.iter().map(|x| self.map_type_ffi(x)).collect();
pub fn define_struct(&mut self, name: &str, atom_fields: Vec<Atom>) -> Result<(), FFIError> {
let mut fields: Vec<_> = atom_fields
.iter()
.map(|x| self.map_type_ffi(x))
.collect::<Result<_, FFIError>>()?;
fields.push(std::ptr::null_mut::<ffi_type>());
let struct_type = ffi_type {
type_: STRUCT,
@@ -96,10 +99,11 @@ impl ForeignFunctionTable {
atom_fields,
},
);
Ok(())
}
fn map_type_ffi(&mut self, source: &Atom) -> *mut ffi_type {
match source {
fn map_type_ffi(&mut self, source: &Atom) -> Result<*mut ffi_type, FFIError> {
Ok(match source {
atom!("sint64") => addr_of_mut!(types::sint64),
atom!("sint32") => addr_of_mut!(types::sint32),
atom!("sint16") => addr_of_mut!(types::sint16),
@@ -116,9 +120,9 @@ impl ForeignFunctionTable {
atom!("f64") => addr_of_mut!(types::double),
struct_name => match self.structs.get_mut(&*struct_name.as_str()) {
Some(ref mut struct_type) => &mut struct_type.ffi_type,
None => unreachable!(),
None => return Err(FFIError::InvalidFFIType),
},
}
})
}
pub(crate) fn load_library(
@@ -133,18 +137,22 @@ impl ForeignFunctionTable {
let symbol_name: CString = CString::new(function.name.clone())?;
let code_ptr: Symbol<*mut c_void> =
library.get(&symbol_name.into_bytes_with_nul())?;
let mut args: Vec<_> = function.args.iter().map(|x| self.map_type_ffi(x)).collect();
let mut args: Vec<_> = function
.args
.iter()
.map(|x| self.map_type_ffi(x))
.collect::<Result<_, FFIError>>()?;
let mut cif: ffi_cif = Default::default();
prep_cif(
&mut cif,
ffi_abi_FFI_DEFAULT_ABI,
args.len(),
self.map_type_ffi(&function.return_value),
self.map_type_ffi(&function.return_value)?,
args.as_mut_ptr(),
)
.unwrap();
let return_struct_name = if (*self.map_type_ffi(&function.return_value)).type_
let return_struct_name = if (*self.map_type_ffi(&function.return_value)?).type_
as u32
== libffi::raw::FFI_TYPE_STRUCT
{
@@ -532,3 +540,11 @@ pub enum FFIError {
FunctionNotFound,
StructNotFound,
}
impl std::fmt::Display for FFIError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
impl Error for FFIError {}

View File

@@ -5148,7 +5148,11 @@ impl Machine {
Err(e) => return Err(e),
};
self.foreign_function_table
.define_struct(&struct_name.as_str(), fields);
.define_struct(&struct_name.as_str(), fields)
.map_err(|err| {
let ffi_error = self.machine_st.ffi_error(err);
self.machine_st.error_form(ffi_error, stub_gen())
})?;
return Ok(());
}
self.machine_st.fail = true;