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

Invalid pointer passed to free() related to ArrayObject #1335

Closed Ye0nny closed 4 months ago

Ye0nny commented 5 months ago

Escargot

Build Steps

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

Describe the bug Invalid pointer passed to free

Test case

testcase

```javascript let t = new Uint32Array ( 3 ) ; t. __proto__ = null ; Object. setPrototypeOf ( t, [ 0.1, 0.1, 0.1 ] ) ; t. length = t [ 0 ] = Infinity ; t. slice ( 2 ) ; t. includes ( 0.1, Infinity, { toString : ( ) => t. length = 0 } ) ; t. shift ( ) ; t. join ( ) ; t. sort ( ) ; ; ```

// poc.js
let t = new Uint32Array ( 3 ) ;
Object. setPrototypeOf ( t, [ 0.1 ] ) ;
t. length = Infinity ;
t. slice ( 2 ) ;

Execution steps & Output

$ ./escargot poc.js
Invalid pointer passed to free()
Aborted

Backtrace

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7031859 in __GI_abort () at abort.c:79
#2  0x000055555625219f in GC_debug_free (p=0x55555679bd40 <Escargot::ArrayObject::DummyArrayElement>) at third_party/GCutil/bdwgc/dbg_mlc.c:798
#3  0x0000555555e013c4 in Escargot::CustomAllocator<Escargot::EncodedSmallValue>::deallocate (this=0x7fffffffb470, __p=0x55555679bd40 <Escargot::ArrayObject::DummyArrayElement>) at src/heap/CustomAllocator.h:116
#4  0x0000555555e009de in Escargot::TightVectorWithNoSize<Escargot::EncodedSmallValue, Escargot::CustomAllocator<Escargot::EncodedSmallValue> >::~TightVectorWithNoSize (this=0xdde58, __in_chrg=<optimized out>)
    at src/util/TightVector.h:353
#5  0x0000555555dfa7b5 in Escargot::ArrayObject::~ArrayObject (this=0xdde30, __in_chrg=<optimized out>) at src/runtime/ArrayObject.h:34
#6  0x0000555555dfae56 in Escargot::ArrayObject::ArrayObject (this=0xdde30, state=..., proto=0xddee0, size=@0x7fffffffb6a0: 9007199254740989, shouldConsiderHole=true) at src/runtime/ArrayObject.cpp:74
#7  0x0000555555dfad66 in Escargot::ArrayObject::ArrayObject (this=0xdde30, state=..., size=@0x7fffffffb6a0: 9007199254740989, shouldConsiderHole=true) at src/runtime/ArrayObject.cpp:69
#8  0x00005555557f0002 in Escargot::arraySpeciesCreate (state=..., originalArray=0x9c480, length=9007199254740989) at src/builtins/BuiltinArray.cpp:130
#9  0x00005555557fa05f in Escargot::builtinArraySlice (state=..., thisValue=..., argc=1, argv=0x7fffffffbce0, newTarget=...) at src/builtins/BuiltinArray.cpp:761
#10 0x0000555555f120f6 in Escargot::NativeFunctionObject::processNativeFunctionCall<false, true> (this=0xdfe30, state=..., receiverSrc=..., argc=1, argv=0x7fffffffbce0, newTarget=...)
    at src/runtime/FunctionObjectInlines.h:312
#11 0x0000555555f1156d in Escargot::NativeFunctionObject::call (this=0xdfe30, state=..., thisValue=..., argc=1, argv=0x7fffffffce98) at src/runtime/NativeFunctionObject.cpp:78
#12 0x0000555555a14b5e in Escargot::Interpreter::interpret (state=0x7fffffffcf40, byteCodeBlock=0xdaf50, programCounter=107271103189728, registerFile=0x7fffffffce80)
    at src/interpreter/ByteCodeInterpreter.cpp:788
#13 0x0000555555bdd1bc in Escargot::Script::execute (this=0x5a070, state=..., isExecuteOnEvalFunction=false, inStrictMode=false) at src/parser/Script.cpp:499
#14 0x00005555557cfc63 in Escargot::ScriptRef::execute (this=0x5a070, state=0x7fffffffd870) at src/api/EscargotPublic.cpp:4715
#15 0x000055555607103d in <lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::operator()(Escargot::ExecutionStateRef *, Escargot::ScriptRef *) const (__closure=0x0, state=0x7fffffffd870,
    script=0x5a070) at src/shell/Shell.cpp:790
#16 0x0000555556071068 in <lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *) () at src/shell/Shell.cpp:791
#17 0x000055555607ad3e in Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<0ul>::apply<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&, Escargot::ExecutionStateRef*&, Escargot::ScriptRef*&> (
    f=@0x7fffffffd700: 0x55555607103f <<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *)>) at src/api/EscargotPublic.h:521
#18 0x000055555607a34a in Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<1ul>::apply<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&, Escargot::ScriptRef*&> (
    f=@0x7fffffffd700: 0x55555607103f <<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *)>, t=std::tuple containing = {...})
    at src/api/EscargotPublic.h:510
#19 0x00005555560797aa in Escargot::EvaluatorUtil::ApplyTupleIntoArgumentsOfVariadicTemplateFunction<2ul>::apply<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&> (f=@0x7fffffffd700: 0x55555607103f <<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *)>,
    t=std::tuple containing = {...}) at src/api/EscargotPublic.h:510
#20 0x000055555607885d in Escargot::EvaluatorUtil::applyTupleIntoArgumentsOfVariadicTemplateFunction<Escargot::ValueRef* (*&)(Escargot::ExecutionStateRef*, Escargot::ScriptRef*), std::tuple<Escargot::ExecutionStateRef*, Escargot::ScriptRef*>&> (f=@0x7fffffffd700: 0x55555607103f <<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *)>,
    t=std::tuple containing = {...}) at src/api/EscargotPublic.h:531
#21 0x0000555556076e71 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 (this=0x0, state=0x7fffffffd870, tuplePtr=0x7fffffffdb60,
    fnPtr=0x55555607103f <<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *)>) at src/api/EscargotPublic.h:612
#22 0x0000555556076eff 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*) () at src/api/EscargotPublic.h:606
#23 0x00005555557cbde1 in Escargot::Evaluator::<lambda(Escargot::ExecutionState&, void*)>::operator()(Escargot::ExecutionState &, void *) const (__closure=0x0, state=..., data=0x7fffffffd990)
    at src/api/EscargotPublic.cpp:1087
#24 0x00005555557cbe1b in Escargot::Evaluator::<lambda(Escargot::ExecutionState&, void*)>::_FUN(Escargot::ExecutionState &, void *) () at src/api/EscargotPublic.cpp:1088
#25 0x0000555555fb1dd5 in Escargot::SandBox::run (this=0x7fffffffda20, scriptRunner=0x5555557cbdf2 <Escargot::Evaluator::<lambda(Escargot::ExecutionState&, void*)>::_FUN(Escargot::ExecutionState &, void *)>,
    data=0x7fffffffd990) at src/runtime/SandBox.cpp:111
#26 0x00005555557cc07a in Escargot::Evaluator::executeFunction (ctx=0xa3af0,
    runner=0x555556076ece <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*)>, data=0x7fffffffdb60,
    data2=0x55555607103f <<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *)>) at src/api/EscargotPublic.cpp:1089
#27 0x0000555556077101 in Escargot::Evaluator::executeImpl<Escargot::ContextRef, Escargot::ScriptRef*> (p=0xa3af0,
    fn=0x55555607103f <<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)>::_FUN(Escargot::ExecutionStateRef *, Escargot::ScriptRef *)>) at src/api/EscargotPublic.h:614
#28 0x000055555607569b in Escargot::Evaluator::execute<Escargot::ScriptRef*, evalScript(Escargot::ContextRef*, Escargot::StringRef*, Escargot::StringRef*, bool, bool)::<lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)> >(Escargot::ContextRef *, <lambda(Escargot::ExecutionStateRef*, Escargot::ScriptRef*)> &&) (ctx=0xa3af0, closure=...) at src/api/EscargotPublic.h:585
#29 0x0000555556071839 in evalScript (context=0xa3af0, source=0xd7f70, srcName=0x78070, shouldPrintScriptResult=false, isModule=false) at src/shell/Shell.cpp:792
#30 0x00005555560742dc in main (argc=2, argv=0x7fffffffe318) at src/shell/Shell.cpp:1143

when executed in release mode

Output

Segmentation fault

Expected behavior

poc.js:4: RangeError: Invalid array length
t. slice ( 2 ) ;
   ^
RangeError: Invalid array length
    at Uint32Array.slice (<anonymous>)
    at poc.js:4:4

Credits: @Ye0nny, @EJueon

clover2123 commented 4 months ago

Fixed in #1337