fix crash when trying to load and ffi library with an invalid type specification
This commit is contained in:
committed by
Bennet Bleßmann
parent
db3f2717bc
commit
34eab2e73a
34
src/ffi.rs
34
src/ffi.rs
@@ -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 {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user