summaryrefslogtreecommitdiff
path: root/ext/ffi/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi/lib.rs')
-rw-r--r--ext/ffi/lib.rs128
1 files changed, 81 insertions, 47 deletions
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index 4c306e7f4..41b2f0a3b 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -130,6 +130,8 @@ impl DynamicLibraryResource {
// By default, Err returned by this function does not tell
// which symbol wasn't exported. So we'll modify the error
// message to include the name of symbol.
+ //
+ // SAFETY: The obtained T symbol is the size of a pointer.
let fn_ptr = match unsafe { self.lib.symbol::<*const c_void>(symbol) } {
Ok(value) => Ok(value),
Err(err) => Err(generic_error(format!(
@@ -164,6 +166,8 @@ impl DynamicLibraryResource {
// By default, Err returned by this function does not tell
// which symbol wasn't exported. So we'll modify the error
// message to include the name of symbol.
+ //
+ // SAFETY: The obtained T symbol is the size of a pointer.
match unsafe { self.lib.symbol::<*const c_void>(&symbol) } {
Ok(value) => Ok(Ok(value)),
Err(err) => Err(generic_error(format!(
@@ -743,55 +747,60 @@ fn ffi_call(
let call_args: Vec<Arg> = call_args
.iter()
.enumerate()
- .map(|(index, ffi_arg)| unsafe {
- ffi_arg.as_arg(*parameter_types.get(index).unwrap())
+ .map(|(index, ffi_arg)| {
+ // SAFETY: the union field is initialized
+ unsafe { ffi_arg.as_arg(*parameter_types.get(index).unwrap()) }
})
.collect();
- Ok(match result_type {
- NativeType::Void => NativeValue {
- void_value: unsafe { cif.call::<()>(fun_ptr, &call_args) },
- },
- NativeType::U8 => NativeValue {
- u8_value: unsafe { cif.call::<u8>(fun_ptr, &call_args) },
- },
- NativeType::I8 => NativeValue {
- i8_value: unsafe { cif.call::<i8>(fun_ptr, &call_args) },
- },
- NativeType::U16 => NativeValue {
- u16_value: unsafe { cif.call::<u16>(fun_ptr, &call_args) },
- },
- NativeType::I16 => NativeValue {
- i16_value: unsafe { cif.call::<i16>(fun_ptr, &call_args) },
- },
- NativeType::U32 => NativeValue {
- u32_value: unsafe { cif.call::<u32>(fun_ptr, &call_args) },
- },
- NativeType::I32 => NativeValue {
- i32_value: unsafe { cif.call::<i32>(fun_ptr, &call_args) },
- },
- NativeType::U64 => NativeValue {
- u64_value: unsafe { cif.call::<u64>(fun_ptr, &call_args) },
- },
- NativeType::I64 => NativeValue {
- i64_value: unsafe { cif.call::<i64>(fun_ptr, &call_args) },
- },
- NativeType::USize => NativeValue {
- usize_value: unsafe { cif.call::<usize>(fun_ptr, &call_args) },
- },
- NativeType::ISize => NativeValue {
- isize_value: unsafe { cif.call::<isize>(fun_ptr, &call_args) },
- },
- NativeType::F32 => NativeValue {
- f32_value: unsafe { cif.call::<f32>(fun_ptr, &call_args) },
- },
- NativeType::F64 => NativeValue {
- f64_value: unsafe { cif.call::<f64>(fun_ptr, &call_args) },
- },
- NativeType::Pointer | NativeType::Function => NativeValue {
- pointer: unsafe { cif.call::<*const u8>(fun_ptr, &call_args) },
- },
- })
+ // SAFETY: types in the `Cif` match the actual calling convention and
+ // types of symbol.
+ unsafe {
+ Ok(match result_type {
+ NativeType::Void => NativeValue {
+ void_value: cif.call::<()>(fun_ptr, &call_args),
+ },
+ NativeType::U8 => NativeValue {
+ u8_value: cif.call::<u8>(fun_ptr, &call_args),
+ },
+ NativeType::I8 => NativeValue {
+ i8_value: cif.call::<i8>(fun_ptr, &call_args),
+ },
+ NativeType::U16 => NativeValue {
+ u16_value: cif.call::<u16>(fun_ptr, &call_args),
+ },
+ NativeType::I16 => NativeValue {
+ i16_value: cif.call::<i16>(fun_ptr, &call_args),
+ },
+ NativeType::U32 => NativeValue {
+ u32_value: cif.call::<u32>(fun_ptr, &call_args),
+ },
+ NativeType::I32 => NativeValue {
+ i32_value: cif.call::<i32>(fun_ptr, &call_args),
+ },
+ NativeType::U64 => NativeValue {
+ u64_value: cif.call::<u64>(fun_ptr, &call_args),
+ },
+ NativeType::I64 => NativeValue {
+ i64_value: cif.call::<i64>(fun_ptr, &call_args),
+ },
+ NativeType::USize => NativeValue {
+ usize_value: cif.call::<usize>(fun_ptr, &call_args),
+ },
+ NativeType::ISize => NativeValue {
+ isize_value: cif.call::<isize>(fun_ptr, &call_args),
+ },
+ NativeType::F32 => NativeValue {
+ f32_value: cif.call::<f32>(fun_ptr, &call_args),
+ },
+ NativeType::F64 => NativeValue {
+ f64_value: cif.call::<f64>(fun_ptr, &call_args),
+ },
+ NativeType::Pointer | NativeType::Function => NativeValue {
+ pointer: cif.call::<*const u8>(fun_ptr, &call_args),
+ },
+ })
+ }
}
struct UnsafeCallbackResource {
@@ -1201,71 +1210,83 @@ fn op_ffi_get_static<'scope>(
return Err(type_error("Invalid FFI static type 'void'"));
}
NativeType::U8 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u8) };
let number: v8::Local<v8::Value> =
v8::Integer::new_from_unsigned(scope, result as u32).into();
number.into()
}
NativeType::I8 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i8) };
let number: v8::Local<v8::Value> =
v8::Integer::new(scope, result as i32).into();
number.into()
}
NativeType::U16 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u16) };
let number: v8::Local<v8::Value> =
v8::Integer::new_from_unsigned(scope, result as u32).into();
number.into()
}
NativeType::I16 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i16) };
let number: v8::Local<v8::Value> =
v8::Integer::new(scope, result as i32).into();
number.into()
}
NativeType::U32 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u32) };
let number: v8::Local<v8::Value> =
v8::Integer::new_from_unsigned(scope, result).into();
number.into()
}
NativeType::I32 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i32) };
let number: v8::Local<v8::Value> = v8::Integer::new(scope, result).into();
number.into()
}
NativeType::U64 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const u64) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_u64(scope, result).into();
big_int.into()
}
NativeType::I64 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const i64) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_i64(scope, result).into();
big_int.into()
}
NativeType::USize => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const usize) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_u64(scope, result as u64).into();
big_int.into()
}
NativeType::ISize => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const isize) };
let big_int: v8::Local<v8::Value> =
v8::BigInt::new_from_i64(scope, result as i64).into();
big_int.into()
}
NativeType::F32 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const f32) };
let number: v8::Local<v8::Value> =
v8::Number::new(scope, result as f64).into();
number.into()
}
NativeType::F64 => {
+ // SAFETY: ptr is user provided
let result = unsafe { ptr::read_unaligned(data_ptr as *const f64) };
let number: v8::Local<v8::Value> = v8::Number::new(scope, result).into();
number.into()
@@ -1339,7 +1360,7 @@ fn op_ffi_call_nonblocking<'scope>(
cif,
ptr,
parameter_types,
- ..
+ result_type,
} = symbol.clone();
ffi_call(call_args, &cif, ptr, &parameter_types, result_type)
});
@@ -1392,6 +1413,8 @@ where
))
} else {
let src = src as *const u8;
+ // SAFETY: src is user defined.
+ // dest is properly aligned and is valid for writes of len * size_of::<T>() bytes.
unsafe { ptr::copy(src, dst.as_mut_ptr(), len) };
Ok(())
}
@@ -1411,6 +1434,8 @@ where
permissions.check(None)?;
let ptr = ptr as *const c_char;
+ // SAFETY: ptr is user provided
+ // lifetime validity is not an issue because we allocate a new string.
Ok(unsafe { CStr::from_ptr(ptr) }.to_str()?.to_string())
}
@@ -1427,6 +1452,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const u8) })
}
@@ -1443,6 +1469,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const i8) })
}
@@ -1459,6 +1486,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const u16) })
}
@@ -1475,6 +1503,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const i16) })
}
@@ -1491,6 +1520,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const u32) })
}
@@ -1507,6 +1537,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const i32) })
}
@@ -1525,6 +1556,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
let result = unsafe { ptr::read_unaligned(ptr as *const u64) };
let big_int: v8::Local<v8::Value> =
@@ -1545,6 +1577,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const f32) })
}
@@ -1561,6 +1594,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check(None)?;
+ // SAFETY: ptr is user provided.
Ok(unsafe { ptr::read_unaligned(ptr as *const f64) })
}