Skip to content

Commit b54ea51

Browse files
committed
Implement boundary check (#243)
1 parent 3ccb072 commit b54ea51

36 files changed

+924
-490
lines changed

crates/lune-std-ffi/src/c/c_arr.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use libffi::middle::Type;
22
use mlua::prelude::*;
33

44
use super::association_names::CARR_INNER;
5-
use super::c_helper::{get_ensured_size, pretty_format_userdata, type_from_userdata};
5+
use super::c_helper::{get_ensured_size, libffi_type_from_userdata, pretty_format_userdata};
66
use super::c_ptr::CPtr;
77
use crate::ffi::ffi_association::{get_association, set_association};
88

@@ -44,13 +44,21 @@ impl CArr {
4444
luatype: &LuaAnyUserData<'lua>,
4545
length: usize,
4646
) -> LuaResult<LuaAnyUserData<'lua>> {
47-
let fields = type_from_userdata(lua, luatype)?;
47+
let fields = libffi_type_from_userdata(lua, luatype)?;
4848
let carr = lua.create_userdata(Self::new(fields, length)?)?;
4949

5050
set_association(lua, CARR_INNER, &carr, luatype)?;
5151
Ok(carr)
5252
}
5353

54+
pub fn get_size(&self) -> usize {
55+
self.size
56+
}
57+
58+
pub fn get_length(&self) -> usize {
59+
self.length
60+
}
61+
5462
pub fn get_type(&self) -> &Type {
5563
&self.struct_type
5664
}
@@ -83,8 +91,8 @@ impl CArr {
8391

8492
impl LuaUserData for CArr {
8593
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
86-
fields.add_field_method_get("size", |_, this| Ok(this.size));
87-
fields.add_field_method_get("length", |_, this| Ok(this.length));
94+
fields.add_field_method_get("size", |_, this| Ok(this.get_size()));
95+
fields.add_field_method_get("length", |_, this| Ok(this.get_length()));
8896
fields.add_field_function_get("inner", |lua, this: LuaAnyUserData| {
8997
let inner: LuaValue = get_association(lua, CARR_INNER, this)?
9098
// It shouldn't happen.
@@ -102,7 +110,7 @@ impl LuaUserData for CArr {
102110
}
103111
});
104112
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
105-
let pointer = CPtr::from_lua_userdata(lua, &this)?;
113+
let pointer = CPtr::new_from_lua_userdata(lua, &this)?;
106114
Ok(pointer)
107115
});
108116
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {

crates/lune-std-ffi/src/c/c_fn.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use libffi::middle::{Cif, Type};
22
use mlua::prelude::*;
33

4-
use super::c_helper::{type_from_userdata, type_list_from_table};
4+
use super::c_helper::{libffi_type_from_userdata, libffi_type_list_from_table};
55

66
// cfn is a type declaration for a function.
77
// Basically, when calling an external function, this type declaration
@@ -36,8 +36,8 @@ impl CFn {
3636
}
3737

3838
pub fn new_from_lua_table(lua: &Lua, args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> {
39-
let args = type_list_from_table(lua, &args)?;
40-
let ret = type_from_userdata(lua, &ret)?;
39+
let args = libffi_type_list_from_table(lua, &args)?;
40+
let ret = libffi_type_from_userdata(lua, &ret)?;
4141
Ok(Self::new(args, ret))
4242
}
4343
}

crates/lune-std-ffi/src/c/c_helper.rs

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,84 @@
1+
#![allow(clippy::inline_always)]
2+
13
use std::ptr::{self, null_mut};
24

35
use libffi::{low, middle::Type, raw};
46
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
57
use mlua::prelude::*;
68

79
use super::association_names::CTYPE_STATIC;
8-
use super::c_arr::CArr;
9-
use super::c_ptr::CPtr;
10-
use super::c_struct::CStruct;
1110
use super::c_type::CTypeStatic;
12-
use crate::ffi::ffi_association::get_association;
13-
use crate::ffi::ffi_helper::FFI_STATUS_NAMES;
11+
use super::types::get_ctype_conv;
12+
use super::{CArr, CPtr, CStruct};
13+
use crate::ffi::{ffi_association::get_association, NativeConvert, FFI_STATUS_NAMES};
14+
15+
// Get the NativeConvert handle from the type UserData
16+
// this is intended to avoid constant table lookups. (eg: struct)
17+
// userdata must live longer than the NativeConvert handle.
18+
// However, c_struct is a strong reference to each field, so this is not a problem.
19+
pub unsafe fn get_conv(userdata: &LuaAnyUserData) -> LuaResult<*const dyn NativeConvert> {
20+
if userdata.is::<CStruct>() {
21+
Ok(userdata.to_pointer().cast::<CStruct>() as *const dyn NativeConvert)
22+
} else {
23+
unsafe { get_ctype_conv(userdata) }
24+
}
25+
}
26+
pub unsafe fn get_conv_list_from_table(
27+
table: &LuaTable,
28+
) -> LuaResult<Vec<*const dyn NativeConvert>> {
29+
let len: usize = table.raw_len();
30+
let mut conv_list = Vec::<*const dyn NativeConvert>::with_capacity(len);
31+
32+
for i in 0..len {
33+
let value: LuaValue = table.raw_get(i + 1)?;
34+
35+
if let LuaValue::UserData(field_type) = value {
36+
conv_list.push(get_conv(&field_type)?);
37+
} else {
38+
return Err(LuaError::external(format!(
39+
"Unexpected field. CStruct, CType or CArr is required for element but got {}",
40+
pretty_format_value(&value, &ValueFormatConfig::new())
41+
)));
42+
}
43+
}
44+
45+
Ok(conv_list)
46+
}
47+
48+
// #[inline(always)]
49+
// pub fn type_size_from_userdata(this: &LuaAnyUserData) -> LuaResult<usize> {
50+
// if this.is::<CStruct>() {
51+
// Ok(this.borrow::<CStruct>()?.get_size())
52+
// } else if this.is::<CArr>() {
53+
// Ok(this.borrow::<CArr>()?.get_size())
54+
// } else {
55+
// ctype_size_from_userdata(this)
56+
// }
57+
// }
1458

1559
// get Vec<libffi_type> from table(array) of c-types userdata
16-
pub fn type_list_from_table(lua: &Lua, table: &LuaTable) -> LuaResult<Vec<Type>> {
60+
pub fn libffi_type_list_from_table(lua: &Lua, table: &LuaTable) -> LuaResult<Vec<Type>> {
1761
let len: usize = table.raw_len();
1862
let mut fields = Vec::with_capacity(len);
1963

2064
for i in 0..len {
2165
// Test required
2266
let value = table.raw_get(i + 1)?;
23-
match value {
24-
LuaValue::UserData(field_type) => {
25-
fields.push(type_from_userdata(lua, &field_type)?);
26-
}
27-
_ => {
28-
return Err(LuaError::external(format!(
29-
"Unexpected field. CStruct, CType or CArr is required for element but got {}",
30-
pretty_format_value(&value, &ValueFormatConfig::new())
31-
)));
32-
}
67+
if let LuaValue::UserData(field_type) = value {
68+
fields.push(libffi_type_from_userdata(lua, &field_type)?);
69+
} else {
70+
return Err(LuaError::external(format!(
71+
"Unexpected field. CStruct, CType or CArr is required for element but got {}",
72+
value.type_name()
73+
)));
3374
}
3475
}
3576

3677
Ok(fields)
3778
}
3879

3980
// get libffi_type from any c-type userdata
40-
pub fn type_from_userdata(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<Type> {
81+
pub fn libffi_type_from_userdata(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<Type> {
4182
if userdata.is::<CStruct>() {
4283
Ok(userdata.borrow::<CStruct>()?.get_type().to_owned())
4384
} else if let Some(t) = get_association(lua, CTYPE_STATIC, userdata)? {

crates/lune-std-ffi/src/c/c_ptr.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
#![allow(clippy::cargo_common_metadata)]
2-
31
use libffi::middle::Type;
42
use mlua::prelude::*;
53

6-
use super::association_names::CPTR_INNER;
7-
use super::c_arr::CArr;
8-
use super::c_helper::pretty_format_userdata;
4+
use super::{association_names::CPTR_INNER, c_helper::pretty_format_userdata, CArr};
95
use crate::ffi::ffi_association::{get_association, set_association};
106

117
pub struct CPtr();
128

139
impl CPtr {
1410
// Create pointer type with '.inner' field
1511
// inner can be CArr, CType or CStruct
16-
pub fn from_lua_userdata<'lua>(
12+
pub fn new_from_lua_userdata<'lua>(
1713
lua: &'lua Lua,
1814
inner: &LuaAnyUserData,
1915
) -> LuaResult<LuaAnyUserData<'lua>> {
@@ -56,7 +52,7 @@ impl LuaUserData for CPtr {
5652

5753
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
5854
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
59-
let pointer = CPtr::from_lua_userdata(lua, &this)?;
55+
let pointer = CPtr::new_from_lua_userdata(lua, &this)?;
6056
Ok(pointer)
6157
});
6258
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {

0 commit comments

Comments
 (0)