Remove callable boundary check (#243)

This commit is contained in:
qwreey 2024-10-23 04:29:32 +00:00
parent b442ba7985
commit 83be2bc96a
No known key found for this signature in database
GPG key ID: D28DB79297A214BD
12 changed files with 61 additions and 61 deletions

View file

@ -12,7 +12,7 @@ See [tests/ffi](../../tests/ffi/README.md)
- Add math operation.
> `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow`
> Provide related methods: `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow` `:max` `:min` `:gt` `:lt`
> Luau cannot handle f64, i64 or i128, so we should provide math operation for it
- Add bit operation

View file

@ -150,7 +150,6 @@ impl FfiConvert for CArrInfo {
impl LuaUserData for CArrInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_meta_field(LuaMetaMethod::Type, "CArr");
fields.add_field_method_get("size", |_, this| Ok(this.get_size()));
fields.add_field_method_get("length", |_, this| Ok(this.get_length()));
fields.add_field_function_get("inner", |lua, this: LuaAnyUserData| {

View file

@ -203,9 +203,6 @@ impl CFnInfo {
}
impl LuaUserData for CFnInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_meta_field(LuaMetaMethod::Type, "CFn");
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
// Subtype
method_provider::provide_ptr(methods);

View file

@ -314,17 +314,17 @@ pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
// get name tag for any c-type userdata
pub fn get_tag_name(userdata: &LuaAnyUserData) -> LuaResult<String> {
Ok(if userdata.is::<CStructInfo>() {
String::from("CStruct")
String::from("CStructInfo")
} else if userdata.is::<CArrInfo>() {
String::from("CArr")
String::from("CArrInfo")
} else if userdata.is::<CPtrInfo>() {
String::from("CPtr")
String::from("CPtrInfo")
} else if userdata.is::<CFnInfo>() {
String::from("CFn")
String::from("CFnInfo")
} else if userdata.is::<CVoidInfo>() {
String::from("CVoid")
String::from("CVoidInfo")
} else if ctype_helper::is_ctype(userdata) {
String::from("CType")
String::from("CTypeInfo")
} else {
String::from("Unknown")
})

View file

@ -5,6 +5,7 @@ mod arr_info;
mod fn_info;
pub mod helper;
mod ptr_info;
mod string_info;
mod struct_info;
mod type_info;
mod types;
@ -15,6 +16,7 @@ pub use self::{
fn_info::CFnInfo,
helper::method_provider,
ptr_info::CPtrInfo,
string_info::CStringInfo,
struct_info::CStructInfo,
type_info::{CTypeCast, CTypeInfo},
types::{ctype_helper, export_c_types, export_fixed_types},
@ -44,5 +46,6 @@ pub fn export_c(lua: &Lua) -> LuaResult<LuaTable> {
.with_function("fn", |lua, (args, ret): (LuaTable, LuaAnyUserData)| {
CFnInfo::from_table(lua, args, ret)
})?
.with_value("string", CStringInfo::new())?
.build_readonly()
}

View file

@ -124,7 +124,6 @@ impl CPtrInfo {
impl LuaUserData for CPtrInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_meta_field(LuaMetaMethod::Type, "CPtr");
fields.add_field_method_get("size", |_, _| Ok(size_of::<usize>()));
fields.add_field_function_get("inner", |lua, this| {
let inner = association::get(lua, CPTR_INNER, this)?

View file

@ -1 +1,11 @@
use mlua::prelude::*;
pub struct CStringInfo();
impl CStringInfo {
pub fn new() -> Self {
Self()
}
}
impl LuaUserData for CStringInfo {}

View file

@ -182,7 +182,6 @@ impl FfiConvert for CStructInfo {
impl LuaUserData for CStructInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_meta_field(LuaMetaMethod::Type, "CStruct");
fields.add_field_method_get("size", |_, this| Ok(this.get_size()));
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {

View file

@ -91,9 +91,8 @@ where
Self: CTypeCast + FfiSignedness + FfiConvert + FfiSize,
{
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_meta_field(LuaMetaMethod::Type, "CType");
fields.add_meta_field(LuaMetaMethod::Type, "CTypeInfo");
fields.add_field_method_get("size", |_, this| Ok(this.get_size()));
fields.add_meta_field(LuaMetaMethod::Type, "CType");
fields.add_field_method_get("signedness", |_, this| Ok(this.get_signedness()));
}

View file

@ -31,9 +31,6 @@ impl CVoidInfo {
}
impl LuaUserData for CVoidInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_meta_field(LuaMetaMethod::Type, "CVoid");
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
method_provider::provide_to_string(methods);
method_provider::provide_ptr(methods);

View file

@ -23,32 +23,32 @@ pub struct CallableData {
const VOID_RESULT_PTR: *mut () = ptr::null_mut();
const ZERO_SIZE_ARG_PTR: *mut *mut c_void = ptr::null_mut();
// Use known size array in stack instead of creating new Vec on heap
macro_rules! create_caller {
($len:expr) => {
|callable: &CallableData, result: LuaValue, args: LuaMultiValue| unsafe {
let mut arg_list: [MaybeUninit<*mut c_void>; $len] = [MaybeUninit::uninit(); $len];
// Get `rvalue: *mut c_void` result pointer
let result_pointer = if callable.result_info.size == 0 {
VOID_RESULT_PTR
} else {
let result_data = result.get_ffi_data()?;
if !result_data.check_inner_boundary(0, callable.result_info.size) {
return Err(LuaError::external("Result boundary check failed"));
}
result_data.get_inner_pointer()
result.get_ffi_data()?.get_inner_pointer()
}
.cast::<c_void>();
// Create `avalue: *mut *mut c_void` argument list
let mut arg_list: [MaybeUninit<*mut c_void>; $len] = [MaybeUninit::uninit(); $len];
for (index, arg) in arg_list.iter_mut().enumerate() {
let arg_value = args
.get(index)
.ok_or_else(|| LuaError::external(format!("argument {index} required")))?
.ok_or_else(|| LuaError::external(format!("Argument {index} required")))?
.as_userdata()
.ok_or_else(|| LuaError::external("argument should be Ref"))?;
.ok_or_else(|| LuaError::external("Argument should be a RefData"))?;
let arg_ref = arg_value.borrow::<RefData>()?;
arg.write(arg_ref.get_inner_pointer().cast::<c_void>());
if let Ok(arg_ref) = arg_value.borrow::<RefData>() {
arg.write(arg_ref.get_inner_pointer().cast::<c_void>());
} else {
return Err(LuaError::external("Argument should be a RefData"));
}
}
ffi_call(
@ -65,6 +65,7 @@ macro_rules! create_caller {
};
}
// Call without arguments
unsafe fn zero_size_caller(
callable: &CallableData,
result: LuaValue,
@ -73,11 +74,7 @@ unsafe fn zero_size_caller(
let result_pointer = if callable.result_info.size == 0 {
VOID_RESULT_PTR
} else {
let result_data = result.get_ffi_data()?;
if !result_data.check_inner_boundary(0, callable.result_info.size) {
return Err(LuaError::external("Result boundary check failed"));
}
result_data.get_inner_pointer()
result.get_ffi_data()?.get_inner_pointer()
}
.cast::<c_void>();
@ -130,31 +127,31 @@ impl CallableData {
return SIZED_CALLERS[arg_len](self, result, args);
}
let mut arg_list = Vec::<*mut c_void>::with_capacity(arg_len);
// Get `rvalue: *mut c_void` result pointer
let result_pointer = if self.result_info.size == 0 {
VOID_RESULT_PTR
} else {
let result_data = result.get_ffi_data()?;
if !result_data.check_inner_boundary(0, self.result_info.size) {
return Err(LuaError::external("Result boundary check failed"));
}
result_data.get_inner_pointer()
result.get_ffi_data()?.get_inner_pointer()
}
.cast::<c_void>();
for index in 0..self.arg_info_list.len() {
// Create `avalue: *mut *mut c_void` argument list
let mut arg_list = Vec::<*mut c_void>::with_capacity(arg_len);
for index in 0..arg_len {
let arg_value = args
.get(index)
.ok_or_else(|| LuaError::external(format!("argument {index} required")))?
.ok_or_else(|| LuaError::external(format!("Argument {index} required")))?
.as_userdata()
.ok_or_else(|| LuaError::external("argument should be Ref"))?;
.ok_or_else(|| LuaError::external("Argument should be a RefData"))?;
let arg_ref = arg_value.borrow::<RefData>()?;
arg_list.push(arg_ref.get_inner_pointer().cast::<c_void>());
if let Ok(arg_ref) = arg_value.borrow::<RefData>() {
arg_list.push(arg_ref.get_inner_pointer().cast::<c_void>());
} else {
return Err(LuaError::external("Argument should be a RefData"));
}
}
// Call libffi::raw::ffi_call
ffi_call(
self.cif,
Some(*self.code.as_safe_fun()),
@ -172,7 +169,7 @@ impl LuaUserData for CallableData {
LuaMetaMethod::Call,
|_lua, this: &CallableData, mut args: LuaMultiValue| {
let result = args.pop_front().ok_or_else(|| {
LuaError::external("First argument must be result data handle or nil")
LuaError::external("First argument 'result' must be a RefData, BoxData or nil")
})?;
unsafe { this.call(result, args) }
},

View file

@ -1,32 +1,32 @@
local ffi = require("@lune/ffi")
local c = ffi.c
assert(typeof(c.int) :: string == "CType")
assert(typeof(c.int) :: string == "CTypeInfo")
assert(tostring(c.int) == "int")
assert(typeof(c.int:ptr()) :: string == "CPtr")
assert(typeof(c.int:ptr()) :: string == "CPtrInfo")
assert(tostring(c.int:ptr()) == "int")
assert(tostring(c.int:arr(5):ptr()) == " <CArr( int, length = 5 )> ")
assert(tostring(c.int:arr(5):ptr()) == " <CArrInfo( int, length = 5 )> ")
assert(typeof(c.int:arr(5)) :: string == "CArr")
assert(typeof(c.int:arr(5)) :: string == "CArrInfo")
assert(tostring(c.int:arr(5)) == " int, length = 5 ")
assert(tostring(c.int:ptr():arr(5)) == " <CPtr(int)>, length = 5 ")
assert(tostring(c.int:ptr():arr(5)) == " <CPtrInfo(int)>, length = 5 ")
assert(typeof(c.fn({ c.int }, c.int)) :: string == "CFn")
assert(typeof(c.fn({ c.int }, c.int)) :: string == "CFnInfo")
assert(tostring(c.fn({ c.int }, c.int)) == " (int) -> int ")
assert(tostring(c.fn({ c.int, ffi.f32 }, c.int)) == " (int, f32) -> int ")
assert(tostring(c.fn({ c.int:ptr() }, c.int)) == " (<CPtr(int)>) -> int ")
assert(tostring(c.fn({ c.int }, c.int:ptr())) == " (int) -> <CPtr(int)> ")
assert(tostring(c.fn({ c.int:ptr() }, c.int:ptr())) == " (<CPtr(int)>) -> <CPtr(int)> ")
assert(tostring(c.fn({ c.int:ptr() }, c.int)) == " (<CPtrInfo(int)>) -> int ")
assert(tostring(c.fn({ c.int }, c.int:ptr())) == " (int) -> <CPtrInfo(int)> ")
assert(tostring(c.fn({ c.int:ptr() }, c.int:ptr())) == " (<CPtrInfo(int)>) -> <CPtrInfo(int)> ")
assert(
tostring(c.fn({ c.int:ptr(), c.int:ptr() }, c.int:ptr()))
== " (<CPtr(int)>, <CPtr(int)>) -> <CPtr(int)> "
== " (<CPtrInfo(int)>, <CPtrInfo(int)>) -> <CPtrInfo(int)> "
)
assert(typeof(c.struct({ c.int, c.char })) :: string == "CStruct")
assert(typeof(c.struct({ c.int, c.char })) :: string == "CStructInfo")
assert(
tostring(c.struct({ c.int, c.char:ptr() }))
== ` int, <CPtr(char)>, size = {c.struct({ c.int, c.char:ptr() }).size} `
== ` int, <CPtrInfo(char)>, size = {c.struct({ c.int, c.char:ptr() }).size} `
)
-- FIXME: add box, ref pretty-print test