Skip to content

Commit e23aaef

Browse files
committed
Improve ffiref (#243)
1 parent 94d8d07 commit e23aaef

File tree

11 files changed

+129
-75
lines changed

11 files changed

+129
-75
lines changed

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use super::{
1010
};
1111
use crate::ffi::{
1212
ffi_association::{get_association, set_association},
13-
FfiBox, GetNativeDataHandle, NativeConvert, NativeDataHandle, NativeSignedness, NativeSize,
13+
FfiBox, GetNativeDataHandle, NativeConvert, NativeDataHandle, NativeSize,
1414
};
1515

1616
// This is a series of some type.
@@ -104,11 +104,6 @@ impl NativeSize for CArr {
104104
self.size
105105
}
106106
}
107-
impl NativeSignedness for CArr {
108-
fn get_signedness(&self) -> bool {
109-
false
110-
}
111-
}
112107
impl NativeConvert for CArr {
113108
// FIXME: FfiBox, FfiRef support required
114109
unsafe fn luavalue_into<'lua>(
@@ -192,7 +187,7 @@ impl LuaUserData for CArr {
192187
if !data_handle.check_boundary(offset, this.get_size()) {
193188
return Err(LuaError::external("Out of bounds"));
194189
}
195-
if !data_handle.check_readable(&userdata, offset, this.get_size()) {
190+
if !data_handle.check_readable(offset, this.get_size()) {
196191
return Err(LuaError::external("Unreadable data handle"));
197192
}
198193

@@ -208,7 +203,7 @@ impl LuaUserData for CArr {
208203
if !data_handle.check_boundary(offset, this.size) {
209204
return Err(LuaError::external("Out of bounds"));
210205
}
211-
if !data_handle.checek_writable(&userdata, offset, this.size) {
206+
if !data_handle.checek_writable(offset, this.size) {
212207
return Err(LuaError::external("Unwritable data handle"));
213208
}
214209

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

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

4-
use super::c_helper::{libffi_type_from_userdata, libffi_type_list_from_table};
4+
use super::c_helper::{
5+
get_conv, get_conv_list_from_table, libffi_type_from_userdata, libffi_type_list_from_table,
6+
};
7+
use crate::ffi::NativeConvert;
58

69
// cfn is a type declaration for a function.
710
// Basically, when calling an external function, this type declaration
@@ -21,24 +24,35 @@ use super::c_helper::{libffi_type_from_userdata, libffi_type_list_from_table};
2124

2225
pub struct CFn {
2326
libffi_cif: Cif,
24-
args: Vec<Type>,
25-
ret: Type,
27+
args_conv: Vec<*const dyn NativeConvert>,
28+
ret_conv: *const dyn NativeConvert,
2629
}
2730

2831
impl CFn {
29-
pub fn new(args: Vec<Type>, ret: Type) -> Self {
30-
let libffi_cif = Cif::new(args.clone(), ret.clone());
32+
pub fn new(
33+
args: Vec<Type>,
34+
ret: Type,
35+
args_conv: Vec<*const dyn NativeConvert>,
36+
ret_conv: *const dyn NativeConvert,
37+
) -> Self {
38+
let libffi_cif: Cif = Cif::new(args.clone(), ret.clone());
3139
Self {
3240
libffi_cif,
33-
args,
34-
ret,
41+
args_conv,
42+
ret_conv,
3543
}
3644
}
3745

3846
pub fn new_from_lua_table(lua: &Lua, args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> {
39-
let args = libffi_type_list_from_table(lua, &args)?;
40-
let ret = libffi_type_from_userdata(lua, &ret)?;
41-
Ok(Self::new(args, ret))
47+
let args_type = libffi_type_list_from_table(lua, &args)?;
48+
let ret_type = libffi_type_from_userdata(lua, &ret)?;
49+
50+
Ok(Self::new(
51+
args_type,
52+
ret_type,
53+
unsafe { get_conv_list_from_table(&args)? },
54+
unsafe { get_conv(&ret)? },
55+
))
4256
}
4357
}
4458

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl CStruct {
5050

5151
// Get tailing padded size of struct
5252
// See http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html
53+
// In here, using get_ensured_size is waste
5354
let size = unsafe { (*struct_type.as_raw_ptr()).size };
5455

5556
Ok(Self {
@@ -91,7 +92,8 @@ impl CStruct {
9192
}
9293

9394
// size of
94-
result.push_str(format!("size = {} ", userdata.borrow::<CStruct>()?.size).as_str());
95+
result
96+
.push_str(format!("size = {} ", userdata.borrow::<CStruct>()?.get_size()).as_str());
9597
Ok(result)
9698
} else {
9799
Err(LuaError::external("failed to get inner type table."))
@@ -206,7 +208,7 @@ impl LuaUserData for CStruct {
206208
if !data_handle.check_boundary(offset, this.get_size()) {
207209
return Err(LuaError::external("Out of bounds"));
208210
}
209-
if !data_handle.check_readable(&userdata, offset, this.get_size()) {
211+
if !data_handle.check_readable(offset, this.get_size()) {
210212
return Err(LuaError::external("Unreadable data handle"));
211213
}
212214

@@ -219,10 +221,10 @@ impl LuaUserData for CStruct {
219221
let offset = offset.unwrap_or(0);
220222

221223
let data_handle = &userdata.get_data_handle()?;
222-
if !data_handle.check_boundary(offset, this.size) {
224+
if !data_handle.check_boundary(offset, this.get_size()) {
223225
return Err(LuaError::external("Out of bounds"));
224226
}
225-
if !data_handle.checek_writable(&userdata, offset, this.size) {
227+
if !data_handle.checek_writable(offset, this.get_size()) {
226228
return Err(LuaError::external("Unwritable data handle"));
227229
}
228230

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ where
164164
if !data_handle.check_boundary(offset, ctype.get_size()) {
165165
return Err(LuaError::external("Out of bounds"));
166166
}
167-
if !data_handle.check_readable(&userdata, offset, ctype.get_size()) {
167+
if !data_handle.check_readable(offset, ctype.get_size()) {
168168
return Err(LuaError::external("Unreadable data handle"));
169169
}
170170

@@ -187,7 +187,7 @@ where
187187
if !data_handle.check_boundary(offset, ctype.get_size()) {
188188
return Err(LuaError::external("Out of bounds"));
189189
}
190-
if !data_handle.checek_writable(&userdata, offset, ctype.get_size()) {
190+
if !data_handle.checek_writable(offset, ctype.get_size()) {
191191
return Err(LuaError::external("Unwritable data handle"));
192192
}
193193

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use core::ffi::c_void;

crates/lune-std-ffi/src/ffi/ffi_box.rs

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,17 @@
11
use std::boxed::Box;
2-
use std::sync::OnceLock;
32

43
use mlua::prelude::*;
54

65
use super::{
76
association_names::REF_INNER,
87
ffi_association::set_association,
9-
ffi_ref::{FfiRef, FfiRefBounds, FfiRefFlag, FfiRefFlagList},
8+
ffi_ref::{FfiRef, FfiRefBounds, FfiRefFlag, FfiRefFlagList, UNSIZED_BOUNDS},
109
NativeDataHandle,
1110
};
1211

13-
static BOX_REF_FLAGS: OnceLock<FfiRefFlagList> = OnceLock::new();
14-
fn get_box_ref_flags() -> FfiRefFlagList {
15-
BOX_REF_FLAGS
16-
.get_or_init(|| {
17-
FfiRefFlagList::new(&[
18-
FfiRefFlag::Offsetable,
19-
FfiRefFlag::Readable,
20-
FfiRefFlag::Writable,
21-
])
22-
})
23-
.to_owned()
24-
}
12+
const BOX_REF_FLAGS: FfiRefFlagList = FfiRefFlagList::new(
13+
FfiRefFlag::Offsetable.value() | FfiRefFlag::Readable.value() | FfiRefFlag::Writable.value(),
14+
);
2515

2616
// It is an untyped, sized memory area that Lua can manage.
2717
// This area is safe within Lua. Operations have their boundaries checked.
@@ -35,6 +25,7 @@ fn get_box_ref_flags() -> FfiRefFlagList {
3525
struct RefData {
3626
address: usize,
3727
offset: usize,
28+
lua_inner_id: i32,
3829
}
3930

4031
pub struct FfiBox {
@@ -77,7 +68,7 @@ impl FfiBox {
7768
this: LuaAnyUserData<'lua>,
7869
offset: Option<isize>,
7970
) -> LuaResult<LuaAnyUserData<'lua>> {
80-
let mut target = this.borrow_mut::<FfiBox>()?;
71+
let target = this.borrow::<FfiBox>()?;
8172
let mut bounds = FfiRefBounds::new(0, target.size());
8273
let mut ptr = target.get_ptr();
8374

@@ -98,14 +89,35 @@ impl FfiBox {
9889
// To deref a box space is to allow lua to read any space,
9990
// which has security issues and is ultimately dangerous.
10091
// Therefore, box:ref():deref() is not allowed.
101-
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), get_box_ref_flags(), bounds))?;
92+
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), BOX_REF_FLAGS, bounds))?;
10293

10394
// Makes box alive longer then ref
10495
set_association(lua, REF_INNER, &luaref, &this)?;
10596

10697
Ok(luaref)
10798
}
10899

100+
// Make FfiRef from box, without any safe features
101+
pub fn luaref_unsafe<'lua>(
102+
lua: &'lua Lua,
103+
this: LuaAnyUserData<'lua>,
104+
offset: Option<isize>,
105+
) -> LuaResult<LuaAnyUserData<'lua>> {
106+
let target = this.borrow::<FfiBox>()?;
107+
let mut ptr = target.get_ptr();
108+
109+
// Calculate offset
110+
if let Some(t) = offset {
111+
ptr = unsafe { target.get_ptr().byte_offset(t) };
112+
}
113+
114+
lua.create_userdata(FfiRef::new(
115+
ptr.cast(),
116+
FfiRefFlagList::all(),
117+
UNSIZED_BOUNDS,
118+
))
119+
}
120+
109121
// Fill every field with 0
110122
pub fn zero(&mut self) {
111123
self.data.fill(0u8);
@@ -130,13 +142,16 @@ impl NativeDataHandle for FfiBox {
130142
self.size() > ((offset as usize) + size)
131143
}
132144
// FIXME
133-
fn checek_writable(&self, userdata: &LuaAnyUserData, offset: isize, size: usize) -> bool {
145+
fn checek_writable(&self, offset: isize, size: usize) -> bool {
134146
true
135147
}
136148
// FIXME
137-
fn check_readable(&self, userdata: &LuaAnyUserData, offset: isize, size: usize) -> bool {
149+
fn check_readable(&self, offset: isize, size: usize) -> bool {
138150
true
139151
}
152+
fn mark_ref(&self, userdata: &LuaAnyUserData, offset: isize, ptr: usize) -> LuaResult<()> {
153+
Ok(())
154+
}
140155
unsafe fn get_pointer(&self, offset: isize) -> *mut () {
141156
self.get_ptr().byte_offset(offset).cast::<()>()
142157
}
@@ -155,8 +170,13 @@ impl LuaUserData for FfiBox {
155170
methods.add_function(
156171
"ref",
157172
|lua, (this, offset): (LuaAnyUserData, Option<isize>)| {
158-
let luaref = FfiBox::luaref(lua, this, offset)?;
159-
Ok(luaref)
173+
FfiBox::luaref(lua, this, offset)
174+
},
175+
);
176+
methods.add_function(
177+
"unsafeRef",
178+
|lua, (this, offset): (LuaAnyUserData, Option<isize>)| {
179+
FfiBox::luaref_unsafe(lua, this, offset)
160180
},
161181
);
162182
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(this.stringify()));

crates/lune-std-ffi/src/ffi/ffi_func.rs

Lines changed: 0 additions & 3 deletions
This file was deleted.

crates/lune-std-ffi/src/ffi/ffi_lib.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use std::ffi::c_void;
2-
use std::sync::LazyLock;
1+
use core::ffi::c_void;
32

43
use dlopen2::symbor::Library;
54
use mlua::prelude::*;
@@ -10,14 +9,12 @@ use super::{
109
ffi_ref::{FfiRef, FfiRefFlag, FfiRefFlagList, UNSIZED_BOUNDS},
1110
};
1211

13-
static LIB_REF_FLAGS: LazyLock<FfiRefFlagList> = LazyLock::new(|| {
14-
FfiRefFlagList::new(&[
15-
FfiRefFlag::Offsetable,
16-
FfiRefFlag::Readable,
17-
FfiRefFlag::Dereferenceable,
18-
FfiRefFlag::Function,
19-
])
20-
});
12+
const LIB_REF_FLAGS: FfiRefFlagList = FfiRefFlagList::new(
13+
FfiRefFlag::Offsetable.value()
14+
| FfiRefFlag::Readable.value()
15+
| FfiRefFlag::Dereferenceable.value()
16+
| FfiRefFlag::Function.value(),
17+
);
2118

2219
pub struct FfiLib(Library);
2320

@@ -50,11 +47,8 @@ impl FfiLib {
5047
.map_err(|err| LuaError::external(format!("{err}")))?
5148
};
5249

53-
let luasym = lua.create_userdata(FfiRef::new(
54-
(*sym).cast(),
55-
(*LIB_REF_FLAGS).clone(),
56-
UNSIZED_BOUNDS,
57-
))?;
50+
let luasym =
51+
lua.create_userdata(FfiRef::new((*sym).cast(), LIB_REF_FLAGS, UNSIZED_BOUNDS))?;
5852

5953
set_association(lua, SYM_INNER, &luasym, &this)?;
6054

crates/lune-std-ffi/src/ffi/ffi_native/readwrite.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use super::super::{FfiBox, FfiRef};
77

88
pub trait NativeDataHandle {
99
fn check_boundary(&self, offset: isize, size: usize) -> bool;
10-
fn check_readable(&self, userdata: &LuaAnyUserData, offset: isize, size: usize) -> bool;
11-
fn checek_writable(&self, userdata: &LuaAnyUserData, offset: isize, size: usize) -> bool;
10+
fn check_readable(&self, offset: isize, size: usize) -> bool;
11+
fn checek_writable(&self, offset: isize, size: usize) -> bool;
12+
fn mark_ref(&self, userdata: &LuaAnyUserData, offset: isize, ptr: usize) -> LuaResult<()>;
1213
unsafe fn get_pointer(&self, offset: isize) -> *mut ();
1314
}
1415

crates/lune-std-ffi/src/ffi/ffi_ref/flags.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@ impl FfiRefFlagList {
2525
pub fn zero() -> Self {
2626
Self(0)
2727
}
28-
pub fn new(flags: &[FfiRefFlag]) -> Self {
29-
let mut value = 0;
30-
for i in flags {
31-
value |= i.value();
32-
}
33-
Self(value)
28+
pub const fn new(flags: u8) -> Self {
29+
Self(flags)
30+
}
31+
pub const fn all() -> Self {
32+
Self(
33+
FfiRefFlag::Dereferenceable.value()
34+
| FfiRefFlag::Readable.value()
35+
| FfiRefFlag::Writable.value()
36+
| FfiRefFlag::Offsetable.value()
37+
| FfiRefFlag::Function.value(),
38+
)
3439
}
3540
fn set(&mut self, value: bool, mask: u8) {
3641
if value {

0 commit comments

Comments
 (0)