Invalid memory access in `GetEntryPoint`
PoC:
function main() {
const v0 = {};
async function v1(v2,v3,v4,v5,v6) {
function v7(v8) {
}
const v9 = v7;
for (const v10 in v0) {
const v12 = await 320832.93626390724;
}
const v13 = v1();
let v15 = 1337;
for (let v17 = 0; v17 < v15; v17 = v17 && 350074.8305491025) {
v15 = v17;
}
const v19 = new Promise(v9);
}
const v20 = v1();
}
main();
Backtrace:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x841f0f66db)
frame #0: 0x00000001026b72ec libChakraCore.dylib`Js::Type::GetEntryPoint(this=0x000000841f0f66c3) const at Type.h:51:57
48 inline TypeId GetTypeId() const { return typeId; }
49 void SetTypeId(TypeId typeId) { this->typeId = typeId; }
50 RecyclableObject* GetPrototype() const { return prototype; }
-> 51 JavascriptMethod GetEntryPoint() const { return entryPoint; }
52 JavascriptLibrary* GetLibrary() const { return javascriptLibrary; }
53 ScriptContext * GetScriptContext() const;
54 Recycler * GetRecycler() const;
Target 0: (ch) stopped.
(lldb) bt 20
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x841f0f66db)
* frame #0: 0x00000001026b72ec libChakraCore.dylib`Js::Type::GetEntryPoint(this=0x000000841f0f66c3) const at Type.h:51:57
frame #1: 0x0000000103686e3d libChakraCore.dylib`Js::RecyclableObject::GetEntryPoint(this=0x0000000102206f0e) const at RecyclableObject.cpp:175:33
frame #2: 0x0000000103036ee4 libChakraCore.dylib`Js::JavascriptConversion::IsCallable(aValue=0x0000000102206f0e) at JavascriptConversion.cpp:41:47
frame #3: 0x0000000103036e47 libChakraCore.dylib`Js::JavascriptConversion::IsCallable(aValue=0x0000000102206f0e) at JavascriptConversion.cpp:35:16
frame #4: 0x0000000103480b95 libChakraCore.dylib`Js::JavascriptPromise::NewInstance(function=0x00000009078f0100, callInfo=(Count = 2, Flags = CallFlags_New, unused = 0)) at JavascriptPromise.cpp:46:37
frame #5: 0x0000000907c01679
frame #6: 0x000000010360d15e libChakraCore.dylib`amd64_CallFunction at JavascriptFunctionA.S:100
frame #7: 0x00000001032c62db libChakraCore.dylib`void* Js::JavascriptFunction::CallFunction<true>(function=0x00000001020e67d0, entryPoint=(0x0000000907c01000), args=Arguments @ 0x00007ffeef40df48, useLargeArgCount=false)(Js::RecyclableObject*, Js::CallInfo, ...), Js::Arguments, bool) at JavascriptFunction.cpp:1364:16
frame #8: 0x00000001032d2a47 libChakraCore.dylib`Js::JavascriptGenerator::CallGenerator(this=0x0000000909434960, data=0x00000001020e5030, resumeKind=Normal) at JavascriptGenerator.cpp:185:26
frame #9: 0x0000000103283904 libChakraCore.dylib`Js::JavascriptAsyncFunction::EntryAsyncSpawnStepNextFunction(function=0x000000090943b460, callInfo=(Count = 1, Flags = CallFlags_Value, unused = 0)) at JavascriptAsyncFunction.cpp:93:31
frame #10: 0x0000000103283ae8 libChakraCore.dylib`Js::JavascriptAsyncFunction::AsyncSpawnStep(stepFunction=0x000000090943b460, generator=0x0000000909434960, resolve=0x000000090943d4e0, reject=0x000000090943d540) at JavascriptAsyncFunction.cpp:151:25
frame #11: 0x00000001032837b6 libChakraCore.dylib`Js::JavascriptAsyncFunction::BeginAsyncFunctionExecution(generator=0x0000000909434960) at JavascriptAsyncFunction.cpp:73:9
frame #12: 0x00000001032835a3 libChakraCore.dylib`Js::JavascriptAsyncFunction::EntryAsyncFunctionImplementation(function=0x0000000907b27880, callInfo=(Count = 1, Flags = CallFlags_Value, unused = 0)) at JavascriptAsyncFunction.cpp:52:12
frame #13: 0x0000000907c0151d
frame #14: 0x000000010360d15e libChakraCore.dylib`amd64_CallFunction at JavascriptFunctionA.S:100
frame #15: 0x00000001032c62db libChakraCore.dylib`void* Js::JavascriptFunction::CallFunction<true>(function=0x00000001020e67d0, entryPoint=(0x0000000907c01000), args=Arguments @ 0x00007ffeef40e5d8, useLargeArgCount=false)(Js::RecyclableObject*, Js::CallInfo, ...), Js::Arguments, bool) at JavascriptFunction.cpp:1364:16
frame #16: 0x00000001032d2a47 libChakraCore.dylib`Js::JavascriptGenerator::CallGenerator(this=0x0000000909434900, data=0x00000001020e5030, resumeKind=Normal) at JavascriptGenerator.cpp:185:26
frame #17: 0x0000000103283904 libChakraCore.dylib`Js::JavascriptAsyncFunction::EntryAsyncSpawnStepNextFunction(function=0x000000090943b3f0, callInfo=(Count = 1, Flags = CallFlags_Value, unused = 0)) at JavascriptAsyncFunction.cpp:93:31
frame #18: 0x0000000103283ae8 libChakraCore.dylib`Js::JavascriptAsyncFunction::AsyncSpawnStep(stepFunction=0x000000090943b3f0, generator=0x0000000909434900, resolve=0x000000090943d420, reject=0x000000090943d480) at JavascriptAsyncFunction.cpp:151:25
frame #19: 0x00000001032837b6 libChakraCore.dylib`Js::JavascriptAsyncFunction::BeginAsyncFunctionExecution(generator=0x0000000909434900) at JavascriptAsyncFunction.cpp:73:9
How to reproduce it:
- ./build.sh -d -j
- ch poc.js
Its backtrace is similar with #6690. I am not sure if their root cause are same.
Hmm - this is a different issue to the ScopeArray points I've been looking at - will investigate seperately.
Simplified repro:
{
let i = 0;
function* v1() {
function v7() {}
for (var v10 in []) {
yield undefined;
}
if(++i < 4)
v1().next()
v7 + 1;
}
}
v1().next();
Use flags -mic:1 -off:simplejit -bgjit-
Note - in the original repro code runs fine until stack overflow occurs - then after top function throws 2nd function down tries to execute to run to completion - error is seen in fulljitted code of the whole function.
Simplified repro triggers the continuation with a control variable instead of waiting for stack overflow - flags force the fulljit to occur sooner without needing 50+ iterations. (or 3000+ to get stack overflow)
Problem is to do with lifetime of the function v7 across a for...in loop containing a yield (or await if using an async function) that is never invoked - slightly obscure; but another one we need to fix if we're keeping generator jit on.