[LuaJIT] Invalid method call causes segmentation fault
naquad opened this issue · comments
Versions
LuaJIT 2.1.1748459687-1
Sol2 3.5.0-1
Clang 20.1.6
Linux x86-64
Minimal reproduction code
#include <iostream>
#define SOL_ALL_SAFETIES_ON 1
#define SOL_CHECK_ARGUMENTS 1
// Sol2 for Lua bindings
#include <sol/sol.hpp>
class SomeClass {
public:
int val;
SomeClass() = default;
SomeClass(int val) : val(val) {}
SomeClass(SomeClass&& other) noexcept = default;
SomeClass& operator=(SomeClass&&) noexcept = default;
SomeClass& operator=(const SomeClass&) = default;
void say_hi() {
std::cout << "Method is working as expected\n";
}
};
int main(int argc, char* argv[]) {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<SomeClass>(
"SomeClass",
sol::no_constructor,
"say_hi", &SomeClass::say_hi,
"check", [](SomeClass& me, sol::this_state L) -> sol::object {
return sol::make_object(L, me.val);
}
);
lua["tpl"] = std::move(SomeClass(123));
lua.script(R"(
-- this fails properly
local ok, err = pcall(function() tpl.say_hi() end)
assert(not ok)
-- and this segfaults
tpl.check() -- <---- mind the "." instead of ":"
)");
return 0;
}Expected result
Lua error / Sol2 exception when trying to call a method as a function.
Actual result
Segmentation fault.
GDB Backtrace
895 }
896 #endif // interop extensibility
897 tracking.use(1);
898 void* rawdata = detail::align_usertype_pointer(memory);
899 void** pudata = static_cast(rawdata);
900 void* udata = *pudata; // <------------------------------------------- CRASHES HERE!
901 return get_no_lua_nil_from(L, udata, index, tracking);
902 }
903
904 static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) {
Backtrace:
#0 0x0000555555581bba in sol::stack::unqualified_getter<sol::detail::as_value_tag, void>::get_no_lua_nil (L=0x7ffff7f9c380, index=1, tracking=...) at /usr/include/sol/stack_get_unqualified.hpp:900
#1 0x0000555555581b63 in sol::stack::unqualified_getter<sol::detail::as_value_tag, void>::get (L=0x7ffff7f9c380, index=1, tracking=...) at /usr/include/sol/stack_get_unqualified.hpp:929
#2 0x0000555555581b14 in sol::stack::stack_detail::unchecked_unqualified_get<sol::detail::as_value_tag > (L=0x7ffff7f9c380, index=1, tracking=...) at /usr/include/sol/stack_core.hpp:712
#3 0x0000555555581ad3 in sol::stack::unqualified_getter<SomeClass, void>::get (L=0x7ffff7f9c380, index=1, tracking=...) at /usr/include/sol/stack_get_unqualified.hpp:181
#4 0x0000555555581514 in sol::stack::stack_detail::unchecked_unqualified_get (L=0x7ffff7f9c380, index=1, tracking=...) at /usr/include/sol/stack_core.hpp:712
#5 0x000055555558bd93 in sol::stack::qualified_getter<SomeClass&, void>::get (L=0x7ffff7f9c380, index=1, tracking=...) at /usr/include/sol/stack_get_unqualified.hpp:256
#6 0x000055555558bd44 in sol::stack::stack_detail::unchecked_get<SomeClass&> (L=0x7ffff7f9c380, index=1, tracking=...) at /usr/include/sol/stack_core.hpp:723
#7 0x000055555558ba63 in sol::stack::stack_detail::unchecked_get_arg<SomeClass&> (L_=0x7ffff7f9c380, index_=1, tracking_=...) at /usr/include/sol/stack_core.hpp:1295
#8 0x000055555555c226 in sol::stack::stack_detail::eval<true, SomeClass&, sol::this_state, 0ul, 1ul, sol::argument_handler<sol::types<sol::basic_object<sol::basic_reference >, SomeClass&, sol::this_state> >&, sol::wrapper<sol::basic_object<sol::basic_reference > ()(SomeClass&, sol::this_state), void>::caller, sol::basic_object<sol::basic_reference > (&)(SomeClass&, sol::this_state)> (L_=0x7ffff7f9c380, start_index_=1, handler_=..., tracking_=..., fx_=...,
fxargs_=@0x7fffffffcd20: 0x55555555c0e0 <main::$0::invoke(SomeClass&, sol::this_state)>) at /usr/include/sol/stack.hpp:182
#9 0x000055555558ba1a in sol::stack::stack_detail::call<true, 0ul, 1ul, sol::basic_object<sol::basic_reference >, SomeClass&, sol::this_state, sol::wrapper<sol::basic_object<sol::basic_reference > ()(SomeClass&, sol::this_state), void>::caller, sol::basic_object<sol::basic_reference > (&)(SomeClass&, sol::this_state)> (argument_types=..., argument_indices=..., L=0x7ffff7f9c380, start_index_=1, fx_=...,
args_=@0x7fffffffcd20: 0x55555555c0e0 <main::$_0::__invoke(SomeClass&, sol::this_state)>) at /usr/include/sol/stack.hpp:204
#10 0x000055555558b976 in sol::stack::call<true, sol::basic_object<sol::basic_reference >, SomeClass&, sol::this_state, sol::wrapper<sol::basic_object<sol::basic_reference > ()(SomeClass&, sol::this_state), void>::caller, sol::basic_object<sol::basic_reference > (&)(SomeClass&, sol::this_state)> (tr=..., ta=..., L=0x7ffff7f9c380, start=1, fx=..., args=@0x7fffffffcd20: 0x55555555c0e0 <main::$_0::__invoke(SomeClass&, sol::this_state)>) at /usr/include/sol/stack.hpp:233
#11 0x000055555558b8bc in sol::stack::call_into_lua<true, true, sol::basic_object<sol::basic_reference >, , SomeClass&, sol::this_state, sol::wrapper<sol::basic_object<sol::basic_reference > ()(SomeClass&, sol::this_state), void>::caller, sol::basic_object<sol::basic_reference > (&)(SomeClass&, sol::this_state)>(sol::types<sol::basic_object<sol::basic_reference >>, sol::types<SomeClass&, sol::this_state>, lua_State*, int, sol::wrapper<sol::basic_object<sol::basic_reference > ()(SomeClass&, sol::this_state), void>::caller&&, sol::basic_object<sol::basic_reference > (&)(SomeClass&, sol::this_state)) (tr=..., ta=..., L=0x7ffff7f9c380, start=1, fx=...,
fxargs=@0x7fffffffcd20: 0x55555555c0e0 <main::$_0::__invoke(SomeClass&, sol::this_state)>) at /usr/include/sol/stack.hpp:281
#12 0x000055555558bec7 in sol::call_detail::agnostic_lua_call_wrapper<sol::basic_object<sol::basic_reference > ()(SomeClass&, sol::this_state), false, false, true, 0, true, void>::call<sol::basic_object<sol::basic_reference > (&)(SomeClass&, sol::this_state)> (L=0x7ffff7f9c380, f=@0x7fffffffcd20: 0x55555555c0e0 <main::$_0::_invoke(SomeClass&, sol::this_state)>) at /usr/include/sol/call.hpp:378
#13 0x000055555555c5bb in sol::call_detail::agnostic_lua_call_wrapper<main::$0, false, false, true, 0, true, void>::callmain::$_0& (L=0x7ffff7f9c380, f=...) at /usr/include/sol/call.hpp:371
#14 0x000055555555c54e in sol::call_detail::lua_call_wrapper<SomeClass, main::$0, false, false, true, 0, true, void>::callmain::$_0& (L=0x7ffff7f9c380, fx=...) at /usr/include/sol/call.hpp:602
#15 0x000055555555c4ee in sol::call_detail::call_wrapped<SomeClass, false, false, 0, true, true, main::$0&> (L=0x7ffff7f9c380, fx=...) at /usr/include/sol/call.hpp:911
#16 0x000055555555b87c in sol::u_detail::binding<char [6], main::$0, SomeClass>::call_with<false, false> (L=0x7ffff7f9c380, target=0x5555555ba728) at /usr/include/sol/usertype_storage.hpp:90
#17 0x000055555555c658 in sol::u_detail::binding<char [6], main::$0, SomeClass>::call<false, false> (L=0x7ffff7f9c380) at /usr/include/sol/usertype_storage.hpp:96
#18 0x000055555557537a in sol::detail::lua_cfunction_trampoline (L=0x7ffff7f9c380, f=0x55555555c600 <sol::u_detail::binding<char [6], main::$0, SomeClass>::call<false, false>(lua_State*)>) at /usr/include/sol/trampoline.hpp:105
#19 0x000055555555c69c in sol::detail::static_trampoline<&sol::u_detail::binding<char [6], main::$0, SomeClass>::call<false, false> > (L=0x7ffff7f9c380) at /usr/include/sol/trampoline.hpp:133
#20 0x000055555555c5f5 in typed_static_trampoline<int (*)(lua_State *), &sol::u_detail::binding<char[6], (lambda at poc.cpp:33:18), SomeClass>::call> (L=0x7ffff7f9c380) at /usr/include/sol/trampoline.hpp:201
#21 0x000055555555b965 in sol::u_detail::binding<char [6], main::$0, SomeClass>::call<false, false> (L=0x7ffff7f9c380) at /usr/include/sol/usertype_storage.hpp:101
#22 0x00007ffff7eebf06 in ?? () from /usr/lib/libluajit-5.1.so.2
#23 0x00007ffff7f02a90 in lua_pcall () from /usr/lib/libluajit-5.1.so.2
#24 0x0000555555567e8c in sol::basic_protected_function<sol::stack_reference, true, sol::basic_reference >::luacall (this=0x7fffffffd198, argcount=0, result_count=-1, h=...) at /usr/include/sol/protected_function.hpp:315
#25 0x0000555555567a37 in sol::basic_protected_function<sol::stack_reference, true, sol::basic_reference >::invoke(sol::types<>, std::integer_sequence, long, sol::detail::protected_handler<true, sol::basic_reference >&) const (this=0x7fffffffd198, n=0, h=...) at /usr/include/sol/protected_function.hpp:346
#26 0x00005555555677e1 in sol::basic_protected_function<sol::stack_reference, true, sol::basic_reference >::call<>() const (this=0x7fffffffd198) at /usr/include/sol/protected_function.hpp:254
#27 0x0000555555565b60 in sol::basic_protected_function<sol::stack_reference, true, sol::basic_reference >::operator()<>() const (this=0x7fffffffd198) at /usr/include/sol/protected_function.hpp:213
#28 0x0000555555565778 in sol::state_view::do_string (this=0x7fffffffd5e0,
code="\n -- this fails properly\n local ok, err = pcall(function() tpl.say_hi() end)\n assert(not ok)\n\n -- and this crashes\n tpl.check() -- <---- mind the "." instead of ":"\n ", chunkname="",
mode=sol::load_mode::any) at /usr/include/sol/state_view.hpp:339
#29 0x00005555555653fe in safe_script<sol::protected_function_result (&)(lua_State*, sol::protected_function_result), (sol::meta::enable_t)0> (this=0x7fffffffd5e0,
code="\n -- this fails properly\n local ok, err = pcall(function() tpl.say_hi() end)\n assert(not ok)\n\n -- and this crashes\n tpl.check() -- <---- mind the "." instead of ":"\n ",
on_error=@0x555555565500: {sol::protected_function_result (lua_State , sol::protected_function_result)} 0x555555565500 <sol::script_default_on_error(lua_State, sol::protected_function_result)>, chunkname="", mode=sol::load_mode::any)
at /usr/include/sol/state_view.hpp:384
#30 0x000055555556538f in sol::state_view::safe_script (this=0x7fffffffd5e0,
code="\n -- this fails properly\n local ok, err = pcall(function() tpl.say_hi() end)\n assert(not ok)\n\n -- and this crashes\n tpl.check() -- <---- mind the "." instead of ":"\n ", chunkname="",
mode=sol::load_mode::any) at /usr/include/sol/state_view.hpp:409
#31 0x00005555555612b8 in sol::state_view::script (this=0x7fffffffd5e0,
code="\n -- this fails properly\n local ok, err = pcall(function() tpl.say_hi() end)\n assert(not ok)\n\n -- and this crashes\n tpl.check() -- <---- mind the "." instead of ":"\n ", chunkname="",
mode=sol::load_mode::any) at /usr/include/sol/state_view.hpp:562
#32 0x0000555555559880 in main (argc=1, argv=0x7fffffffd738) at poc.cpp:40
Additional notes
Linking against Lua 5.4 handles the invalid call gracefully:
Method is working as expected
[sol2] An error occurred and has been passed to an error handler: sol: runtime error: [string "..."]:3: stack index 1, expected userdata, received no value: value is not a valid userdata (bad argument into 'sol::basic_object<sol::basic_reference<false>>(SomeTemplate<int> &, sol::this_state)')
stack traceback:
[C]: in field 'check'
[string "..."]:3: in main chunk
terminate called after throwing an instance of 'sol::error'
what(): sol: runtime error: [string "..."]:3: stack index 1, expected userdata, received no value: value is not a valid userdata (bad argument into 'sol::basic_object<sol::basic_reference<false>>(SomeTemplate<int> &, sol::this_state)')
stack traceback:
[C]: in field 'check'
[string "..."]:3: in main chunk
[1] 1178868 IOT instruction (core dumped) ./main
I think you need to load as a "safe_script" to have an exception instead of abort.
safe_script is having SIGSEGV too.