diff --git a/crates/luaffi/src/future.rs b/crates/luaffi/src/future.rs index d29414b..19e4300 100644 --- a/crates/luaffi/src/future.rs +++ b/crates/luaffi/src/future.rs @@ -156,7 +156,12 @@ impl lua_pollable { pub fn is_valid(&self) -> bool { // TODO: signature check can currently read out-of-bounds if lua code for some reason yields // a cdata of size less than 8 bytes that is not a lua_future. there is no easy way to fix - // afaik this because there is no way to find the size of a cdata payload using the C API. + // AFAIK this because there is no way to find the size of a cdata payload using the C API. + // unfortunately we have to trust that the user won't do that right now. + // + // the only "saving grace" is that the user should never be running untrusted code anyway, + // because this whole project is based on the ffi library which should never be exposed to + // untrusted code in the first place. self.sig == SIGNATURE } } diff --git a/crates/luaffi/src/lib.rs b/crates/luaffi/src/lib.rs index 8342791..e243b94 100644 --- a/crates/luaffi/src/lib.rs +++ b/crates/luaffi/src/lib.rs @@ -941,75 +941,43 @@ impl_ptr_intoabi!(Option<&'static T>); #[cfg(feature = "option_ref_abi")] impl_ptr_intoabi!(Option<&'static mut T>); -// -// SAFETY: `FromFfi` for *mutable* references is safe because it is guaranteed that no two Rust code -// called via FFI can be running at the same time on the same OS thread (no Lua reentrancy). -// -// i.e. The call stack will always look something like this: -// -// * Runtime (LuaJIT/Rust) -> Lua (via C) -> Rust (via FFI): This is SAFE and the only use case we -// support. All references (mutable or not) to Rust user objects will be dropped before -// returning to Lua. -// -// * Runtime (LuaJIT/Rust) -> Lua (via C) -> Rust (via FFI) -> Lua (via callback): This is UNSAFE -// because we cannot prevent the Lua callback from calling back into Rust code via FFI which -// could violate exclusive borrow semantics. This is prevented by not implementing `FromFfi` for -// function pointers (see below). -// -// The runtime does not keep any references to Rust user objects boxed in cdata (futures are the -// only exception; their ownership is transferred to the runtime via yield). -// -macro_rules! impl_ref_fromabi { - ($ty:ty) => { - unsafe impl<'s, T> FromFfi for $ty - where - T: Type, - { - type From = Option<$ty>; +unsafe impl<'s, T> FromFfi for &'s T +where + T: Type, +{ + type From = Option<&'s T>; - fn prelude(arg: &str) -> impl Display { - display!(r#"assert(not rawequal({arg}, nil), "argument '{arg}' cannot be nil"); "#) - } + fn prelude(arg: &str) -> impl Display { + display!(r#"assert(not rawequal({arg}, nil), "argument '{arg}' cannot be nil"); "#) + } - fn convert(from: Self::From) -> Self { - // SAFETY: we already checked that the reference is nonnull from the lua side - debug_assert!( - from.is_some(), - "<{}>::convert() called on a null reference when it was checked to be nonnull", - stringify!($ty), - ); + fn convert(from: Self::From) -> Self { + // SAFETY: we already checked that the reference is nonnull from the lua side + debug_assert!( + from.is_some(), + "<{}>::convert() called on a null reference when it was checked to be nonnull", + stringify!($ty), + ); - unsafe { from.unwrap_unchecked() } - } - } - }; + unsafe { from.unwrap_unchecked() } + } } -impl_ref_fromabi!(&'s T); -impl_ref_fromabi!(&'s mut T); - // // SAFETY: `IntoFfi` only for 'static references because we cannot guarantee that the pointer will // not outlive the pointee otherwise. // -macro_rules! impl_ref_intoabi { - ($ty:ty) => { - unsafe impl IntoFfi for $ty - where - T: Type, - { - type Into = Self; +unsafe impl IntoFfi for &'static T +where + T: Type, +{ + type Into = Self; - fn convert(self) -> Self::Into { - self - } - } - }; + fn convert(self) -> Self::Into { + self + } } -impl_ref_intoabi!(&'static T); -impl_ref_intoabi!(&'static mut T); - // // SAFETY: No `FromFfi` and `IntoFfi` for arrays because passing or returning them by value is not a // thing in C (they are just pointers). @@ -1084,13 +1052,6 @@ macro_rules! impl_externcfn { }; ($ty:ident, fn($($arg:ident),*) -> $ret:ident) => { - // - // SAFETY: No `FromFfi` for function pointers because of borrow safety invariants (see above - // in `&mut T`). - // - // We also can't implement `IntoFfi` because we can't call `FromFfi` and `IntoFfi` for the - // function's respective argument and return values. - // unsafe impl<$($arg,)* $ret> Type for $ty<($($arg,)*), $ret> where $($arg: Type,)* @@ -1145,12 +1106,24 @@ impl_externcfn!(fn(A, B, C, D, E, F, G) -> H); impl_externcfn!(fn(A, B, C, D, E, F, G, H) -> I); impl_externcfn!(fn(A, B, C, D, E, F, G, H, I) -> J); +impl<'s> Annotation for &'s [u8] { + fn annotation() -> impl Display { + "string" + } +} + impl<'s> Annotation for &'s str { fn annotation() -> impl Display { "string" } } +impl Annotation for Vec { + fn annotation() -> impl Display { + "string" + } +} + impl Annotation for String { fn annotation() -> impl Display { "string"