Skip to content

[Bug] Segmentation Fault in chaiscript::Boxed_Number::get_as via async result interpolation #635

@oneafter

Description

@oneafter

Description

We discovered a Segmentation Fault in ChaiScript when retrieving and using the result of an asynchronous function call. The crash occurs in chaiscript::Boxed_Number::get_as when attempting to convert the return value of a finished async task to a string.

The ASAN report indicates an invalid memory read at an unknown address, suggesting memory corruption or improper handling of Boxed_Value lifetime across threads.

Environment

  • OS: Linux x86_64
  • Complier: Clang
  • Build Configuration: Release mode with ASan enabled.

Vulnerability Details

  • Target: ChaiScript
  • Vulnerability Type: Segmentation Fault (Memory Corruption / Thread Safety)
  • Function: chaiscript::Boxed_Number::get_as
  • Location: include/chaiscript/dispatchkit/boxed_number.hpp
  • Root Cause Analysis:
  1. The PoC runs a function in a separate thread using async. The function performs a loop of assignments (:=) and returns an integer.
  2. The main thread calls fut1.get() to retrieve the result.
  3. The result is immediately used in string interpolation: print(" ${fut1.get()} ").
  4. This triggers Boxed_Number::to_string -> Boxed_Number::get_as.
  5. The crash happens inside get_as, implying that the Boxed_Value returned by the future holds invalid internal state or points to memory that is no longer valid (possibly freed when the worker thread terminated).

Reproduce

  1. Build ChaiScript with Release optimization and ASAN enabled.
  2. Run with the crashing file:
poc
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()} ")
./chai crash.chai
ASAN report
AddressSanitizer:DEADLYSIGNAL
=================================================================
==30140==ERROR: AddressSanitizer: SEGV on unknown address 0x7fc7de1f5420 (pc 0x55f5131ff2e5 bp 0x7ffc19b44f30 sp 0x7ffc19b44e30 T0)
==30140==The signal is caused by a READ memory access.
    #0 0x55f5131ff2e5 in int chaiscript::Boxed_Number::get_as<int>() const /src/ChaiScript/include/chaiscript/dispatchkit/boxed_number.hpp
    #1 0x55f51330adc5 in chaiscript::Boxed_Number::to_string[abi:cxx11]() const /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/boxed_number.hpp
    #2 0x55f5133a7b2b in decltype(auto) auto chaiscript::dispatch::detail::make_callable_impl<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*)() const, false, true, false, false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Number const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, chaiscript::dispatch::detail::Function_Signature<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::dispatch::detail::Function_Params<chaiscript::Boxed_Number const&>, false, true, false, false>)::'lambda'(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, auto&&...)::operator()<chaiscript::Boxed_Number>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, auto&&...) const /src/ChaiScript/static_libs/../include/chaiscript/dispatchkit/../utility/../dispatchkit/register_function.hpp:35:19
    #3 0x55f5133a7b2b in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> chaiscript::dispatch::detail::call_func<auto chaiscript::dispatch::detail::make_callable_impl<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*)() const, false, true, false, false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Number const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, chaiscript::dispatch::detail::Function_Signature<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::dispatch::detail::Function_Params<chaiscript::Boxed_Number const&>, false, true, false, false>)::'lambda'(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, auto&&...), std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Number const&, 0ul>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (*)(chaiscript::Boxed_Number const&), std::integer_sequence<unsigned long, 0ul>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::* const&)() const, chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/proxy_functions_detail.hpp:88:16
    #4 0x55f5133a7761 in chaiscript::Boxed_Value chaiscript::dispatch::detail::call_func<auto chaiscript::dispatch::detail::make_callable_impl<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*)() const, false, true, false, false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Number const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, chaiscript::dispatch::detail::Function_Signature<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::dispatch::detail::Function_Params<chaiscript::Boxed_Number const&>, false, true, false, false>)::'lambda'(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, auto&&...), std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Number const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (*)(chaiscript::Boxed_Number const&), std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::* const&)() const, chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/proxy_functions_detail.hpp:102:45
    #5 0x55f5133a7761 in chaiscript::dispatch::Proxy_Function_Callable_Impl<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number const&), auto chaiscript::dispatch::detail::make_callable_impl<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*)() const, false, true, false, false, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Number const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, chaiscript::dispatch::detail::Function_Signature<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::dispatch::detail::Function_Params<chaiscript::Boxed_Number const&>, false, true, false, false>)::'lambda'(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> (chaiscript::Boxed_Number::*&&)() const, auto&&...)>::do_call(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/proxy_functions.hpp:546:16
    #6 0x55f5131f6353 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
    #7 0x55f5131f6353 in chaiscript::Boxed_Value chaiscript::dispatch::dispatch<std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base>>>>(std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base>>> const&, chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) /src/ChaiScript/include/chaiscript/dispatchkit/proxy_functions.hpp:803:22
    #8 0x55f5131eedee in chaiscript::detail::Dispatch_Function::do_call(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) const /src/ChaiScript/include/chaiscript/dispatchkit/dispatchkit.hpp:271:16
    #9 0x55f5136e1fde in chaiscript::dispatch::Proxy_Function_Base::operator()(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/proxy_functions.hpp:181:18
    #10 0x55f5136e1fde in chaiscript::Boxed_Value chaiscript::eval::Fun_Call_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::do_eval_internal<true>(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:318:18
    #11 0x55f5136e1089 in chaiscript::eval::Fun_Call_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:343:105
    #12 0x55f5136a11e8 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
    #13 0x55f51370ac7e in chaiscript::eval::Binary_Operator_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:222:39
    #14 0x55f5136a11e8 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
    #15 0x55f51370ac2d in chaiscript::eval::Binary_Operator_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:221:39
    #16 0x55f5136a11e8 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
    #17 0x55f51370ac2d in chaiscript::eval::Binary_Operator_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:221:39
    #18 0x55f5136a11e8 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
    #19 0x55f51370ac2d in chaiscript::eval::Binary_Operator_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:221:39
    #20 0x55f5136a11e8 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
    #21 0x55f5136e1785 in chaiscript::Boxed_Value chaiscript::eval::Fun_Call_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::do_eval_internal<true>(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:308:35
    #22 0x55f5136e1089 in chaiscript::eval::Fun_Call_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:343:105
    #23 0x55f5136a11e8 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
    #24 0x55f5137f5774 in chaiscript::eval::File_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:1126:43
    #25 0x55f5136a11e8 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
    #26 0x55f5131a8b1e in chaiscript::ChaiScript_Basic::do_eval(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool) /src/ChaiScript/include/chaiscript/language/chaiscript_engine.hpp:85:19
    #27 0x55f5131a1c5e in chaiscript::ChaiScript_Basic::eval(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::shared_ptr<chaiscript::detail::Exception_Handler_Base> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) /src/ChaiScript/include/chaiscript/language/chaiscript_engine.hpp:645:16
    #28 0x55f5131a1c5e in chaiscript::ChaiScript_Basic::eval_file(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::shared_ptr<chaiscript::detail::Exception_Handler_Base> const&) /src/ChaiScript/include/chaiscript/language/chaiscript_engine.hpp:660:14
    #29 0x55f51319a1c5 in main /src/ChaiScript/src/main.cpp:338:16
    #30 0x7fc7e33e51c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #31 0x7fc7e33e528a in __libc_start_main csu/../csu/libc-start.c:360:3
    #32 0x55f5130a0b34 in _start (/src/ChaiScript/build_afl/chai+0x199b34) (BuildId: 8364a862145966bbe9fb7af8769bd28a4608a787)

==30140==Register values:
rax = 0x0000000000000000  rbx = 0x00007fc7e1445f20  rcx = 0x000055f5142f9470  rdx = 0x0000000000000003  
rdi = 0x00007fc7de1f5420  rsi = 0x0000000000000003  rbp = 0x00007ffc19b44f30  rsp = 0x00007ffc19b44e30  
 r8 = 0x00007fffffffff01   r9 = 0x000055f5138e1001  r10 = 0x00007fc7e39656b0  r11 = 0x00000ff97c713fb0  
r12 = 0x00007fc7e15ccba0  r13 = 0x000055f5138e1060  r14 = 0x000055f5138e1060  r15 = 0x00007fc7e1445f00  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /src/ChaiScript/include/chaiscript/dispatchkit/boxed_number.hpp in int chaiscript::Boxed_Number::get_as<int>() const
==30140==ABORTING

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions