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);
|
self.table.extend(other.table);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define_struct(&mut self, name: &str, atom_fields: Vec<Atom>) {
|
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();
|
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>());
|
fields.push(std::ptr::null_mut::<ffi_type>());
|
||||||
let struct_type = ffi_type {
|
let struct_type = ffi_type {
|
||||||
type_: STRUCT,
|
type_: STRUCT,
|
||||||
@@ -96,10 +99,11 @@ impl ForeignFunctionTable {
|
|||||||
atom_fields,
|
atom_fields,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_type_ffi(&mut self, source: &Atom) -> *mut ffi_type {
|
fn map_type_ffi(&mut self, source: &Atom) -> Result<*mut ffi_type, FFIError> {
|
||||||
match source {
|
Ok(match source {
|
||||||
atom!("sint64") => addr_of_mut!(types::sint64),
|
atom!("sint64") => addr_of_mut!(types::sint64),
|
||||||
atom!("sint32") => addr_of_mut!(types::sint32),
|
atom!("sint32") => addr_of_mut!(types::sint32),
|
||||||
atom!("sint16") => addr_of_mut!(types::sint16),
|
atom!("sint16") => addr_of_mut!(types::sint16),
|
||||||
@@ -116,9 +120,9 @@ impl ForeignFunctionTable {
|
|||||||
atom!("f64") => addr_of_mut!(types::double),
|
atom!("f64") => addr_of_mut!(types::double),
|
||||||
struct_name => match self.structs.get_mut(&*struct_name.as_str()) {
|
struct_name => match self.structs.get_mut(&*struct_name.as_str()) {
|
||||||
Some(ref mut struct_type) => &mut struct_type.ffi_type,
|
Some(ref mut struct_type) => &mut struct_type.ffi_type,
|
||||||
None => unreachable!(),
|
None => return Err(FFIError::InvalidFFIType),
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn load_library(
|
pub(crate) fn load_library(
|
||||||
@@ -133,18 +137,22 @@ impl ForeignFunctionTable {
|
|||||||
let symbol_name: CString = CString::new(function.name.clone())?;
|
let symbol_name: CString = CString::new(function.name.clone())?;
|
||||||
let code_ptr: Symbol<*mut c_void> =
|
let code_ptr: Symbol<*mut c_void> =
|
||||||
library.get(&symbol_name.into_bytes_with_nul())?;
|
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();
|
let mut cif: ffi_cif = Default::default();
|
||||||
prep_cif(
|
prep_cif(
|
||||||
&mut cif,
|
&mut cif,
|
||||||
ffi_abi_FFI_DEFAULT_ABI,
|
ffi_abi_FFI_DEFAULT_ABI,
|
||||||
args.len(),
|
args.len(),
|
||||||
self.map_type_ffi(&function.return_value),
|
self.map_type_ffi(&function.return_value)?,
|
||||||
args.as_mut_ptr(),
|
args.as_mut_ptr(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.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
|
as u32
|
||||||
== libffi::raw::FFI_TYPE_STRUCT
|
== libffi::raw::FFI_TYPE_STRUCT
|
||||||
{
|
{
|
||||||
@@ -532,3 +540,11 @@ pub enum FFIError {
|
|||||||
FunctionNotFound,
|
FunctionNotFound,
|
||||||
StructNotFound,
|
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),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
self.foreign_function_table
|
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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
|
|||||||
@@ -163,7 +163,22 @@ fn ffi_return_values() {
|
|||||||
// but there is currently no other easy way to get the dynamic library file path as an input into a load_module_test test
|
// but there is currently no other easy way to get the dynamic library file path as an input into a load_module_test test
|
||||||
std::env::set_var("ffi_return_values_LIB", dynlib_path);
|
std::env::set_var("ffi_return_values_LIB", dynlib_path);
|
||||||
|
|
||||||
// FIXME u32 and u64 have an incorrect result
|
// i8- -42,u8-73,i16- -3054,u16-49374,i32- -200211438,u32-3235819520,i64- -859901580039547648,u64- 859901580039547648,f32-3.1415927410125732,f64-6.283185307179586
|
||||||
|
let expected = format!(
|
||||||
|
"i8- {},u8-{},i16- {},u16-{},i32- {},u32-{},i64- {},u64- {},f32-{},f64-{}",
|
||||||
|
-42,
|
||||||
|
73,
|
||||||
|
-0xBEE,
|
||||||
|
0xC0DE,
|
||||||
|
-0xBEEFBEE,
|
||||||
|
0xC0DEB000u32,
|
||||||
|
-0xBEEFBEE5C0DEB00i64,
|
||||||
|
0xBEEFBEE5C0DEB00u64,
|
||||||
|
std::f32::consts::PI as f64,
|
||||||
|
std::f64::consts::TAU
|
||||||
|
);
|
||||||
|
|
||||||
|
// FIXME all but u8, f32 and f64 are wrong!?!?
|
||||||
load_module_test(
|
load_module_test(
|
||||||
"tests-pl/ffi_return_values.pl",
|
"tests-pl/ffi_return_values.pl",
|
||||||
"i8-214,u8-73,i16-18,u16-222,i32-18,u32-0,i64-0,u64- -4789548415587584,f32-3.1415927410125732,f64-6.283185307179586",
|
"i8-214,u8-73,i16-18,u16-222,i32-18,u32-0,i64-0,u64- -4789548415587584,f32-3.1415927410125732,f64-6.283185307179586",
|
||||||
|
|||||||
Reference in New Issue
Block a user