Skip to content

Commit e687152

Browse files
committed
Check that type passed to scoped userdata self argument is userdata.
If passed type is non-userdata we try to get a pointer (which will be null) that triggers an assertion. Having a check also allow us to generate right error message. Fixes #569
1 parent c4956db commit e687152

2 files changed

Lines changed: 28 additions & 11 deletions

File tree

src/userdata/registry.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::userdata::{
1414
borrow_userdata_scoped, borrow_userdata_scoped_mut, AnyUserData, MetaMethod, TypeIdHints, UserData,
1515
UserDataFields, UserDataMethods, UserDataStorage,
1616
};
17-
use crate::util::{get_userdata, short_type_name};
17+
use crate::util::short_type_name;
1818
use crate::value::Value;
1919

2020
#[cfg(feature = "async")]
@@ -143,16 +143,16 @@ impl<T> UserDataRegistry<T> {
143143
method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
144144
}))
145145
}
146-
#[rustfmt::skip]
147-
UserDataType::Unique(target_ptr)
148-
if get_userdata::<UserDataStorage<T>>(state, self_index) as *mut c_void == target_ptr =>
149-
{
146+
UserDataType::Unique(target_ptr) if ffi::lua_touserdata(state, self_index) == target_ptr => {
150147
let ud = target_ptr as *mut UserDataStorage<T>;
151148
try_self_arg!((*ud).try_borrow_scoped(|ud| {
152149
method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
153150
}))
154151
}
155-
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
152+
UserDataType::Unique(_) => {
153+
try_self_arg!(rawlua.get_userdata_type_id::<T>(state, self_index));
154+
Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch))
155+
}
156156
}
157157
})
158158
}
@@ -192,16 +192,16 @@ impl<T> UserDataRegistry<T> {
192192
method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
193193
}))
194194
}
195-
#[rustfmt::skip]
196-
UserDataType::Unique(target_ptr)
197-
if get_userdata::<UserDataStorage<T>>(state, self_index) as *mut c_void == target_ptr =>
198-
{
195+
UserDataType::Unique(target_ptr) if ffi::lua_touserdata(state, self_index) == target_ptr => {
199196
let ud = target_ptr as *mut UserDataStorage<T>;
200197
try_self_arg!((*ud).try_borrow_scoped_mut(|ud| {
201198
method(rawlua.lua(), ud, args?)?.push_into_stack_multi(rawlua)
202199
}))
203200
}
204-
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
201+
UserDataType::Unique(_) => {
202+
try_self_arg!(rawlua.get_userdata_type_id::<T>(state, self_index));
203+
Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch))
204+
}
205205
}
206206
})
207207
}

tests/scope.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,23 @@ fn test_scope_userdata_mismatch() -> Result<()> {
276276
Err(other) => panic!("wrong error type {other:?}"),
277277
Ok(_) => panic!("incorrectly returned Ok"),
278278
}
279+
280+
// Pass non-userdata type
281+
let err = inc.call::<()>((&au, 321)).err().unwrap();
282+
match err {
283+
Error::CallbackError { ref cause, .. } => match cause.as_ref() {
284+
Error::BadArgument { to, pos, name, cause } => {
285+
assert_eq!(to.as_deref(), Some("MyUserData.inc"));
286+
assert_eq!(*pos, 1);
287+
assert_eq!(name.as_deref(), Some("self"));
288+
assert!(matches!(*cause.as_ref(), Error::FromLuaConversionError { .. }));
289+
}
290+
other => panic!("wrong error type {other:?}"),
291+
},
292+
other => panic!("wrong error type {other:?}"),
293+
}
294+
let err_msg = "bad argument `self` to `MyUserData.inc`: error converting Lua number to userdata (expected userdata of type 'MyUserData')";
295+
assert!(err.to_string().contains(err_msg));
279296
Ok(())
280297
})?;
281298

0 commit comments

Comments
 (0)