Samsung / escargot

Escargot is a lightweight JavaScript engine designed specifically for resource-constrained environments.
GNU Lesser General Public License v2.1
261 stars 43 forks source link

dynamic-stack-buffer-overflow JSC::Yarr::Interpreter<unsigned char>::interpret() #1379

Open 7331akasokoan opened 2 weeks ago

7331akasokoan commented 2 weeks ago

commit: d398f1ece3bae25c00465aea7f00b548d1131241

build setting:

cmake -DCMAKE_CXX_FLAGS=-fsanitize=address -DESCARGOT_MODE=debug -DESCARGOT_OUTPUT=shell -GNinja

poc.js:

const v0 = /(?<v>>||||`|^||||||||||(?<c>(?<d>.)?).)+(?<c>(?<d>.D*))\b/dsyig;
v0.kwstIndex = "2";
v0.test("nud");

ASAN report:

=================================================================
==44525==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7ffd79505130 at pc 0x55d4114d7279 bp 0x7ffd79504f80 sp 0x7ffd79504f70
WRITE of size 4 at 0x7ffd79505130 thread T0
    #0 0x55d4114d7278 in JSC::Yarr::Interpreter<unsigned char>::interpret() (/home/fuzzer/escargot/escargot+0xbd1278)
    #1 0x55d4114d4af9 in JSC::Yarr::interpret(JSC::Yarr::BytecodePattern*, unsigned char const*, unsigned int, unsigned int, unsigned int*) /home/fuzzer/escargot/third_party/yarr/YarrInterpreter.cpp:2769
    #2 0x55d4113b39cf in Escargot::RegExpObject::match(Escargot::ExecutionState&, Escargot::String*, Escargot::RegexMatchResult&, bool, unsigned long) /home/fuzzer/escargot/src/runtime/RegExpObject.cpp:361
    #3 0x55d410cf924c in Escargot::builtinRegExpTest(Escargot::ExecutionState&, Escargot::Value, unsigned long, Escargot::Value*, Escargot::Optional<Escargot::Object*>) (/home/fuzzer/escargot/escargot+0x3f324c)
    #4 0x55d411342ee6 in Escargot::Value Escargot::NativeFunctionObject::processNativeFunctionCall<false, true>(Escargot::ExecutionState&, Escargot::Value const&, unsigned long, Escargot::Value*, Escargot::Optional<Escargot::Object*>) /home/fuzzer/escargot/src/runtime/FunctionObjectInlines.h:312
    #5 0x55d41134233f in Escargot::NativeFunctionObject::call(Escargot::ExecutionState&, Escargot::Value const&, unsigned long, Escargot::Value*) /home/fuzzer/escargot/src/runtime/NativeFunctionObject.cpp:78
    #6 0x55d410e245e0 in Escargot::Interpreter::interpret(Escargot::ExecutionState*, Escargot::ByteCodeBlock*, unsigned long, Escargot::Value*) /home/fuzzer/escargot/src/interpreter/ByteCodeInterpreter.cpp:791
    #7 0x55d41100396e in Escargot::Script::execute(Escargot::ExecutionState&, bool, bool) /home/fuzzer/escargot/src/parser/Script.cpp:499
    #8 0x55d410bcb87e in Escargot::ScriptRef::execute(Escargot::ExecutionStateRef*) /home/fuzzer/escargot/src/api/EscargotPublic.cpp:4722
    #9 0x55d4114a76cc in operator() /home/fuzzer/escargot/src/shell/Shell.cpp:790
    #10 0x55d4114a76f7 in _FUN /home/fuzzer/escargot/src/shell/Shell.cpp:791
    #11 0x55d4114b14b3 in decltype (((forward<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>)({parm#1}))((forward<Escargot::ExecutionStateRef*&>)({parm#3}), (forward<Escargot::ScriptRef*&>)({parm#3}))) Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<0ul>::apply<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&, Escargot::ExecutionStateRef*&, Escargot::ScriptRef*&>(Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&, Escargot::ExecutionStateRef*&, Escargot::ScriptRef*&) /home/fuzzer/escargot/src/api/EscargotPublic.h:521
    #12 0x55d4114b0ad2 in decltype (Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<0ul>::apply((forward<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>)({parm#1}), (forward<std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>)({parm#2}), (get<(1ul)-(1)>)((forward<std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>)({parm#2})), (forward<Escargot::ScriptRef*&>)({parm#3}))) Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<1ul>::apply<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&, Escargot::ScriptRef*&>(Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&, Escargot::ScriptRef*&) /home/fuzzer/escargot/src/api/EscargotPublic.h:510
    #13 0x55d4114b0092 in decltype (Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<1ul>::apply((forward<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>)({parm#1}), (forward<std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>)({parm#2}), (get<(2ul)-(1)>)((forward<std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>)({parm#2})))) Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<2ul>::apply<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>(Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&) /home/fuzzer/escargot/src/api/EscargotPublic.h:510
    #14 0x55d4114af24c in decltype (Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<std::tuple_size<std::decay<std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>::type>::value>::apply((forward<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>)({parm#1}), (forward<std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>)({parm#2}))) Escargot::EvaluatorUtil::applyTupleIntoArgumentsOfVariadicTemplateFunction<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&>(Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&) /home/fuzzer/escargot/src/api/EscargotPublic.h:531
    #15 0x55d4114ad8bc in Escargot::Evaluator::executeImpl<Escargot::ContextRef, Escargot::ScriptRef*>(Escargot::ContextRef*, Escargot::ValueRef* (*)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), Escargot::ScriptRef*)::{lambda(Escargot::ExecutionStateRef*, void*, void*)#1}::operator()(Escargot::ExecutionStateRef*, void*, void*) const /home/fuzzer/escargot/src/api/EscargotPublic.h:612
    #16 0x55d4114ad94a in Escargot::Evaluator::executeImpl<Escargot::ContextRef, Escargot::ScriptRef*>(Escargot::ContextRef*, Escargot::ValueRef* (*)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), Escargot::ScriptRef*)::{lambda(Escargot::ExecutionStateRef*, void*, void*)#1}::_FUN(Escargot::ExecutionStateRef*, void*, void*) /home/fuzzer/escargot/src/api/EscargotPublic.h:606
    #17 0x55d410bc79f0 in operator() /home/fuzzer/escargot/src/api/EscargotPublic.cpp:1094
    #18 0x55d410bc7a2a in _FUN /home/fuzzer/escargot/src/api/EscargotPublic.cpp:1095
    #19 0x55d4113e4a08 in Escargot::SandBox::run(Escargot::Value (*)(Escargot::ExecutionState&, void*), void*) /home/fuzzer/escargot/src/runtime/SandBox.cpp:111
    #20 0x55d410bc7c88 in Escargot::Evaluator::executeFunction(Escargot::ContextRef*, Escargot::ValueRef* (*)(Escargot::ExecutionStateRef*, void*, void*), void*, void*) /home/fuzzer/escargot/src/api/EscargotPublic.cpp:1096
    #21 0x55d4114adb46 in Escargot::Evaluator::EvaluatorResult Escargot::Evaluator::executeImpl<Escargot::ContextRef, Escargot::ScriptRef*>(Escargot::ContextRef*, Escargot::ValueRef* (*)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), Escargot::ScriptRef*) /home/fuzzer/escargot/src/api/EscargotPublic.h:614
    #22 0x55d4114ac0bb in execute<Escargot::ScriptRef*, evalScript(Escargot::ContextRef*, Escargot::StringRef*, Escargot::StringRef*, bool, bool)::<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)> > /home/fuzzer/escargot/src/api/EscargotPublic.h:585
    #23 0x55d4114a7ee1 in evalScript /home/fuzzer/escargot/src/shell/Shell.cpp:792
    #24 0x55d4114aa9cd in main /home/fuzzer/escargot/src/shell/Shell.cpp:1149
    #25 0x7ff273c68d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #26 0x7ff273c68e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #27 0x55d410ba88a4 in _start (/home/fuzzer/escargot/escargot+0x2a28a4)

Address 0x7ffd79505130 is located in stack of thread T0 at offset 320 in frame
    #0 0x55d4114d49fa in JSC::Yarr::interpret(JSC::Yarr::BytecodePattern*, unsigned char const*, unsigned int, unsigned int, unsigned int*) /home/fuzzer/escargot/third_party/yarr/YarrInterpreter.cpp:2768

  This frame has 1 object(s):
    [48, 120) '<unknown>' <== Memory access at offset 320 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow (/home/fuzzer/escargot/escargot+0xbd1278) in JSC::Yarr::Interpreter<unsigned char>::interpret()
Shadow bytes around the buggy address:
  0x10002f2989d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10002f2989e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10002f2989f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
  0x10002f298a00: f1 f1 f1 f1 00 00 00 00 00 00 00 00 00 f3 f3 f3
  0x10002f298a10: f3 f3 00 00 00 00 00 00 00 00 00 00 ca ca ca ca
=>0x10002f298a20: 00 00 00 00 00 00[cb]cb cb cb cb cb 00 00 00 00
  0x10002f298a30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10002f298a40: 00 00 f1 f1 f1 f1 f8 f2 f8 f2 04 f2 04 f2 f8 f2
  0x10002f298a50: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 00
  0x10002f298a60: 00 00 00 00 00 f2 f2 f2 f2 f2 00 00 00 00 00 00
  0x10002f298a70: 00 f2 f2 f2 f2 f2 00 00 00 00 00 f2 f2 f2 f2 f2
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==44525==ABORTING