summaryrefslogtreecommitdiff
path: root/ext/ffi
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2023-01-21 07:51:14 -0800
committerGitHub <noreply@github.com>2023-01-21 21:21:14 +0530
commit59289255411b902588619fd7d2f6e3e48af11d82 (patch)
treea328e565abb1695e57c99538d6482f62e5008cad /ext/ffi
parent638b6ef554676422c43cc5c0ae2285ba369740bf (diff)
fix(ext/ffi): disallow empty ffi structs (#17487)
This patch makes `NativeType` to `libffi::middle::Type` conversion failliable and w.t disallows struct with empty fields. libffi does not handle "empty" struct because they don't exist in C (or Rust). Fixes #17481
Diffstat (limited to 'ext/ffi')
-rw-r--r--ext/ffi/call.rs4
-rw-r--r--ext/ffi/callback.rs17
-rw-r--r--ext/ffi/dlfcn.rs5
-rw-r--r--ext/ffi/symbol.rs27
4 files changed, 36 insertions, 17 deletions
diff --git a/ext/ffi/call.rs b/ext/ffi/call.rs
index 2cfd5cef0..731460af9 100644
--- a/ext/ffi/call.rs
+++ b/ext/ffi/call.rs
@@ -278,7 +278,7 @@ where
permissions.check(None)?;
};
- let symbol = PtrSymbol::new(pointer, &def);
+ let symbol = PtrSymbol::new(pointer, &def)?;
let call_args = ffi_parse_args(scope, parameters, &def.parameters)?;
let def_result = def.result.clone();
@@ -379,7 +379,7 @@ where
permissions.check(None)?;
};
- let symbol = PtrSymbol::new(pointer, &def);
+ let symbol = PtrSymbol::new(pointer, &def)?;
let call_args = ffi_parse_args(scope, parameters, &def.parameters)?;
let out_buffer = out_buffer
diff --git a/ext/ffi/callback.rs b/ext/ffi/callback.rs
index d6ef51823..1558d950e 100644
--- a/ext/ffi/callback.rs
+++ b/ext/ffi/callback.rs
@@ -40,18 +40,19 @@ pub struct PtrSymbol {
}
impl PtrSymbol {
- pub fn new(fn_ptr: usize, def: &ForeignFunction) -> Self {
+ pub fn new(fn_ptr: usize, def: &ForeignFunction) -> Result<Self, AnyError> {
let ptr = libffi::middle::CodePtr::from_ptr(fn_ptr as _);
let cif = libffi::middle::Cif::new(
def
.parameters
.clone()
.into_iter()
- .map(libffi::middle::Type::from),
- def.result.clone().into(),
+ .map(libffi::middle::Type::try_from)
+ .collect::<Result<Vec<_>, _>>()?,
+ def.result.clone().try_into()?,
);
- Self { cif, ptr }
+ Ok(Self { cif, ptr })
}
}
@@ -578,8 +579,12 @@ where
waker: None,
}));
let cif = Cif::new(
- args.parameters.into_iter().map(libffi::middle::Type::from),
- libffi::middle::Type::from(args.result),
+ args
+ .parameters
+ .into_iter()
+ .map(libffi::middle::Type::try_from)
+ .collect::<Result<Vec<_>, _>>()?,
+ libffi::middle::Type::try_from(args.result)?,
);
// SAFETY: CallbackInfo is leaked, is not null and stays valid as long as the callback exists.
diff --git a/ext/ffi/dlfcn.rs b/ext/ffi/dlfcn.rs
index eeff2c8a7..a6b870c30 100644
--- a/ext/ffi/dlfcn.rs
+++ b/ext/ffi/dlfcn.rs
@@ -166,8 +166,9 @@ where
.parameters
.clone()
.into_iter()
- .map(libffi::middle::Type::from),
- foreign_fn.result.clone().into(),
+ .map(libffi::middle::Type::try_from)
+ .collect::<Result<Vec<_>, _>>()?,
+ foreign_fn.result.clone().try_into()?,
);
let func_key = v8::String::new(scope, &symbol_key).unwrap();
diff --git a/ext/ffi/symbol.rs b/ext/ffi/symbol.rs
index bccef79b1..bfe150f78 100644
--- a/ext/ffi/symbol.rs
+++ b/ext/ffi/symbol.rs
@@ -1,5 +1,8 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+use deno_core::error::type_error;
+use deno_core::error::AnyError;
+
/// Defines the accepted types that can be used as
/// parameters and return values in FFI.
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq)]
@@ -25,9 +28,11 @@ pub enum NativeType {
Struct(Box<[NativeType]>),
}
-impl From<NativeType> for libffi::middle::Type {
- fn from(native_type: NativeType) -> Self {
- match native_type {
+impl TryFrom<NativeType> for libffi::middle::Type {
+ type Error = AnyError;
+
+ fn try_from(native_type: NativeType) -> Result<Self, Self::Error> {
+ Ok(match native_type {
NativeType::Void => libffi::middle::Type::void(),
NativeType::U8 | NativeType::Bool => libffi::middle::Type::u8(),
NativeType::I8 => libffi::middle::Type::i8(),
@@ -44,10 +49,18 @@ impl From<NativeType> for libffi::middle::Type {
NativeType::Pointer | NativeType::Buffer | NativeType::Function => {
libffi::middle::Type::pointer()
}
- NativeType::Struct(fields) => libffi::middle::Type::structure(
- fields.iter().map(|field| field.clone().into()),
- ),
- }
+ NativeType::Struct(fields) => {
+ libffi::middle::Type::structure(match fields.len() > 0 {
+ true => fields
+ .iter()
+ .map(|field| field.clone().try_into())
+ .collect::<Result<Vec<_>, _>>()?,
+ false => {
+ return Err(type_error("Struct must have at least one field"))
+ }
+ })
+ }
+ })
}
}