Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation Fault in Js::ScopeSlots::GetCount #6678

Closed
bin2415 opened this issue Apr 7, 2021 · 6 comments · Fixed by #6700
Closed

Segmentation Fault in Js::ScopeSlots::GetCount #6678

bin2415 opened this issue Apr 7, 2021 · 6 comments · Fixed by #6700

Comments

@bin2415
Copy link

bin2415 commented Apr 7, 2021

PoC:

function main() {
async function v0(v1,v2,v3,v4) {
    for (let v8 = 0; v8 < 1337; v8++) {
        const v9 = class V9 {
            constructor(v11,v12,v13) {
                const v14 = !v8;
            }
            isView(v16,...v17) {
            }
            atan(v19) {
            }
            isFinite(v21,v22,v23) {
            }
        };
        const v24 = await v2;
    }
}
const v25 = v0();
CollectGarbage();
}
main();

backtrace:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x00000001032d02dd libChakraCore.dylib`Js::ScopeSlots::GetCount(this=0x00007ffeefbfe058) const at FunctionBody.h:3513:66
    frame #1: 0x0000000103683263 libChakraCore.dylib`Js::JavascriptOperators::OP_CloneScopeSlots(slotArray=0x0000000000000000, scriptContext=0x0000000908808258) at JavascriptOperators.cpp:7681:74
    frame #2: 0x000000090832044d
    frame #3: 0x0000000103c0d15e libChakraCore.dylib`amd64_CallFunction at JavascriptFunctionA.S:100
    frame #4: 0x00000001038c62db libChakraCore.dylib`void* Js::JavascriptFunction::CallFunction<true>(function=0x00000001007e67d0, entryPoint=(libChakraCore.dylib`NativeCodeGenerator::CheckCodeGenThunk(Js::RecyclableObject*, Js::CallInfo, ...)), args=Arguments @ 0x00007ffeefbfe238, useLargeArgCount=false)(Js::RecyclableObject*, Js::CallInfo, ...), Js::Arguments, bool) at JavascriptFunction.cpp:1364:16
    frame #5: 0x00000001038d2a47 libChakraCore.dylib`Js::JavascriptGenerator::CallGenerator(this=0x0000000908249060, data=0x00000001007e5030, resumeKind=Normal) at JavascriptGenerator.cpp:185:26
    frame #6: 0x0000000103883904 libChakraCore.dylib`Js::JavascriptAsyncFunction::EntryAsyncSpawnStepNextFunction(function=0x00000009082d2850, callInfo=(Count = 1, Flags = CallFlags_Value, unused = 0)) at JavascriptAsyncFunction.cpp:93:31
    frame #7: 0x0000000103883ae8 libChakraCore.dylib`Js::JavascriptAsyncFunction::AsyncSpawnStep(stepFunction=0x00000009082d2850, generator=0x0000000908249060, resolve=0x00000009082402a0, reject=0x0000000908240300) at JavascriptAsyncFunction.cpp:151:25
    frame #8: 0x0000000103884577 libChakraCore.dylib`Js::JavascriptAsyncFunction::EntryAsyncSpawnCallStepFunction(function=0x00000009082d2770, callInfo=(Count = 2, Flags = CallFlags_Value, unused = 0)) at JavascriptAsyncFunction.cpp:130:5
    frame #9: 0x0000000103a873e6 libChakraCore.dylib`Js::JavascriptPromise::EntryReactionTaskFunction(function=0x00000009082d70a0, callInfo=(Count = 1, Flags = CallFlags_None, unused = 0)) at JavascriptPromise.cpp:1074:37
    frame #10: 0x0000000103c0d15e libChakraCore.dylib`amd64_CallFunction at JavascriptFunctionA.S:100
    frame #11: 0x00000001038c62db libChakraCore.dylib`void* Js::JavascriptFunction::CallFunction<true>(function=0x00000009082d70a0, entryPoint=(libChakraCore.dylib`Js::JavascriptPromise::EntryReactionTaskFunction(Js::RecyclableObject*, Js::CallInfo, ...) at JavascriptPromise.cpp:1037), args=Arguments @ 0x00007ffeefbfe9f0, useLargeArgCount=false)(Js::RecyclableObject*, Js::CallInfo, ...), Js::Arguments, bool) at JavascriptFunction.cpp:1364:16
    frame #12: 0x00000001038c65ff libChakraCore.dylib`Js::JavascriptFunction::CallRootFunctionInternal(obj=0x00000009082d70a0, args=Arguments @ 0x00007ffeefbfea60, scriptContext=0x0000000908808258, inScript=true) at JavascriptFunction.cpp:772:24
    frame #13: 0x00000001038c643c libChakraCore.dylib`Js::JavascriptFunction::CallRootFunction(obj=0x00000009082d70a0, args=<unavailable>, scriptContext=0x0000000908808258, inScript=true) at JavascriptFunction.cpp:717:15
    frame #14: 0x00000001038c63e1 libChakraCore.dylib`Js::JavascriptFunction::CallRootFunction(this=0x00000009082d70a0, args=<unavailable>, scriptContext=0x0000000908808258, inScript=true) at JavascriptFunction.cpp:832:16
    frame #15: 0x0000000102928525 libChakraCore.dylib`JsCallFunction::$_67::operator(this=0x00007ffeefbfeed0, scriptContext=0x0000000908808258, _actionEntryPopper=0x00007ffeefbfeeb0)(Js::ScriptContext*, TTD::TTDJsRTActionResultAutoRecorder&) const at Jsrt.cpp:2842:41
    frame #16: 0x0000000102927eb4 libChakraCore.dylib`_JsErrorCode ContextAPIWrapper<false, JsCallFunction::$_67>(this=0x00007ffeefbfee68, scriptContext=0x0000000908808258)::'lambda'(Js::ScriptContext*)::operator()(Js::ScriptContext*) const at JsrtInternal.h:237:16
    frame #17: 0x0000000102927884 libChakraCore.dylib`_JsErrorCode ContextAPIWrapper_Core<false, _JsErrorCode ContextAPIWrapper<false, JsCallFunction::$_67>(JsCallFunction::$_67)::'lambda'(Js::ScriptContext*)>(fn=(anonymous class) @ 0x00007ffeefbfee68) at JsrtInternal.h:192:23
    frame #18: 0x00000001028e3d46 libChakraCore.dylib`_JsErrorCode ContextAPIWrapper<false, JsCallFunction::$_67>(fn=(anonymous class) @ 0x00007ffeefbfeed0) at JsrtInternal.h:235:27
    frame #19: 0x00000001028e3d09 libChakraCore.dylib`::JsCallFunction(function=0x00000009082d70a0, args=0x00007ffeefbfefa0, cargs=1, result=0x00007ffeefbfef98) at Jsrt.cpp:2804:12
    frame #20: 0x000000010000bdeb ch`ChakraRTInterface::JsCallFunction(function=0x00000009082d70a0, arguments=0x00007ffeefbfefa0, argumentCount=1, result=0x00007ffeefbfef98) at ChakraRtInterface.h:416:149
    frame #21: 0x000000010001b35a ch`WScriptJsrt::CallbackMessage::CallFunction(this=0x0000000100307b70, fileName="/Users/cpang/Desktop/graduate/javascript/JS_Fuzzing/chakracore/crash2/Poc.js") at WScriptJsrt.cpp:1988:21
    frame #22: 0x000000010001b23d ch`WScriptJsrt::CallbackMessage::Call(this=0x0000000100307b70, fileName="/Users/cpang/Desktop/graduate/javascript/JS_Fuzzing/chakracore/crash2/Poc.js") at WScriptJsrt.cpp:1959:12
    frame #23: 0x000000010000543e ch`MessageQueue::ProcessAll(this=0x000000010770ae80, fileName="/Users/cpang/Desktop/graduate/javascript/JS_Fuzzing/chakracore/crash2/Poc.js") at MessageQueue.h:256:18

How to reproduce:

- ./build.sh -d -j
- ch -collectGarbage ./poc.js

The error code:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x00000001042d02dd libChakraCore.dylib`Js::ScopeSlots::GetCount(this=0x00007ffeefbfe058) const at FunctionBody.h:3513:66
   3510
   3511         size_t GetCount() const
   3512         {
-> 3513             return ::Math::PointerCastToIntegralTruncate<size_t>(slotArray[EncodedSlotCountSlotIndex]);
   3514         }
   3515
   3516         void SetCount(uint count)
@MadProbe
Copy link
Contributor

MadProbe commented Apr 7, 2021

FYI, this issue isn't reproducable on windows 10 in interpreted and dynapogo modes.

@bin2415
Copy link
Author

bin2415 commented Apr 7, 2021

It is reproducable on Ubuntu 18.04 and Mac OS 11.2 when built with debug version.

@ppenzin
Copy link
Member

ppenzin commented Apr 8, 2021

This is due to Js::JavascriptOperators::OP_CloneScopeSlots getting slotArray == nullptr.

I can reproduce the bug in Ubuntu 18 (WSL). However CollectGarbage (both the call and engine switch) is not needed, also the reproducer can be reduced to this:

function main() {
async function v0(v2) {
    for (let v8 = 0; v8 < 1337; v8++) {
        const v9 = class V9 {
            constructor(v11,v12,v13) {
                const v14 = !v8;
            }
        };
        const v24 = await v2;
    }
}
const v25 = v0();
}
main();

Command would then become ./ch poc.js.

@rhuanjl
Copy link
Collaborator

rhuanjl commented Apr 8, 2021

This is a new bug from jitting generators, will need to fix this or re-disable generator jit :( before release.

@rhuanjl
Copy link
Collaborator

rhuanjl commented Apr 8, 2021

I think it's to do with the handling of OpCode::CloneInnerScopeSlots in IRBuilder.cpp - hopefully will be able to write a fix this weekend.

@rhuanjl
Copy link
Collaborator

rhuanjl commented Apr 11, 2021

Reduced further:

async function v0() {
    for (let v8 = 0; v8 < 1337; v8++) {
        function foo () {v8}
        await undefined;
    }
}
v0();

The problem is v8 not being restored properly after await - only happens if v8 is declared with let AND referenced in a different inner scope (hence the function def - I swapped out the class definition to simplify)

I'm working on a fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants