chakra-core / ChakraCore

ChakraCore is an open source Javascript engine with a C API.
MIT License
9.1k stars 1.19k forks source link

for-loop optimization causes a null pointer exception #6817

Open YiWen-y opened 2 years ago

YiWen-y commented 2 years ago

Version:

chakra-1.11.24.0

Description:

For the TestCase below, after judging that !p is true in line 2, the function should return directly, but chakra terminates the program abnormally. Through the stack information of the program#1 0x00007ffff34ddece in ByteCodeGenerator::EmitInvertedLoop ( this=0x7fffffffb4e0, outerLoop=0x7ff7f0b72da0, invertedLoop=0x7ff7f0b75030, funcInfo=0x7ff7f0b74800), maybe there is a problem in optimizing the for loop.

TestCase:

var NISLFuzzingFunc = function(p) {
    if (!p) return;
    var a = 0;
    for (var h = 0;; ++h) {
        for (var r = 0; r < 1; ++r) {
            a = r;
        }
    }
};
var NISLParameter0 = false;
var NISLCallingResult = NISLFuzzingFunc(NISLParameter0);
print(NISLCallingResult);

Command:

~/ChakraCore/out/Release/ch TestCase.js 

Output:

Aborted (core dumped)

Backtrace (using gdb debugging) :

gdb -q -args ~/ChakraCore-1.11.24/out/Debug/ch TestCase.js 
Reading symbols from ~/ChakraCore-1.11.24/out/Debug/ch...done.
(gdb) r
Starting program: ~/ChakraCore-1.11.24/out/Debug/ch TestCase.js 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ff7f242f700 (LWP 8102)]
[New Thread 0x7ff7f1bff700 (LWP 8103)]
[New Thread 0x7ff7f13fe700 (LWP 8104)]

Thread 1 "ch" received signal SIGSEGV, Segmentation fault.
0x00007ffff34dcc75 in EmitBooleanExpression (expr=0x0, trueLabel=10, falseLabel=4, byteCodeGenerator=0x7fffffffb4e0, funcInfo=0x7ff7f0b74800, trueFallthrough=true, falseFallthrough=false)
    at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:8835
8835        switch (expr->nop)
(gdb) bt
#0  0x00007ffff34dcc75 in EmitBooleanExpression (expr=0x0, trueLabel=10, falseLabel=4, byteCodeGenerator=0x7fffffffb4e0, funcInfo=0x7ff7f0b74800, trueFallthrough=true, falseFallthrough=false)
    at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:8835
#1  0x00007ffff34ddece in ByteCodeGenerator::EmitInvertedLoop (this=0x7fffffffb4e0, outerLoop=0x7ff7f0b72da0, invertedLoop=0x7ff7f0b75030, funcInfo=0x7ff7f0b74800)
    at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:9170
#2  0x00007ffff34bbff7 in Emit (pnode=0x7ff7f0b72da0, byteCodeGenerator=0x7fffffffb4e0, funcInfo=0x7ff7f0b74800, fReturnValue=0, isConstructorCall=false, bindingNameLocation=4294967295, isTopLevel=true)
    at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:11085
#3  0x00007ffff34b82de in ByteCodeGenerator::EmitTopLevelStatement (this=0x7fffffffb4e0, stmt=0x7ff7f0b72da0, funcInfo=0x7ff7f0b74800, fReturnValue=0) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:956
#4  0x00007ffff34c73ed in ByteCodeGenerator::EmitFunctionBody (this=0x7fffffffb4e0, funcInfo=0x7ff7f0b74800) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:2507
#5  0x00007ffff34ca160 in ByteCodeGenerator::EmitOneFunction (this=0x7fffffffb4e0, pnodeFnc=0x7ff7f0b722d0) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:3132
#6  0x00007ffff34c7880 in ByteCodeGenerator::EmitScopeList (this=0x7fffffffb4e0, pnode=0x7ff7f0b722d0, breakOnBodyScopeNode=0x0) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:3423
#7  0x00007ffff34c79dd in ByteCodeGenerator::EmitScopeList (this=0x7fffffffb4e0, pnode=0x7ff7f0b72170, breakOnBodyScopeNode=0x0) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:3436
#8  0x00007ffff34c786b in ByteCodeGenerator::EmitScopeList (this=0x7fffffffb4e0, pnode=0x7ff7f0b72030, breakOnBodyScopeNode=0x0) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:3420
#9  0x00007ffff34c7646 in ByteCodeGenerator::EmitProgram (this=0x7fffffffb4e0, pnodeProg=0x7ff7f0b72030) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:2541
#10 0x00007ffff34fffb1 in ByteCodeGenerator::Generate (pnodeProg=0x7ff7f0b72030, grfscr=4112, byteCodeGenerator=0x7fffffffb4e0, ppRootFunc=0x7fffffffb778, sourceIndex=0, forceNoNative=false, parser=0x7fffffffb9f0, functionRef=0x0)
    at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeGenerator.cpp:2021
#11 0x00007ffff3503a8d in GenerateByteCode (pnode=0x7ff7f0b72030, grfscr=4112, scriptContext=0x5555561af538, ppRootFunc=0x7fffffffb778, sourceIndex=0, forceNoNative=false, parser=0x7fffffffb9f0, pse=0x7fffffffc930, parentScopeInfo=0x0, functionRef=0x0)
    at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeGenerator.cpp:2192
#12 0x00007ffff33c514a in Js::ScriptContext::GenerateRootFunction (this=0x5555561af538, parseTree=0x7ff7f0b72030, sourceIndex=0, parser=0x7fffffffb9f0, grfscr=4112, pse=0x7fffffffc930, rootDisplayName=0x7ffff43d3f80 <Js::Constants::GlobalCode> u"Global code")
    at ~/ChakraCore-1.11.24/lib/Runtime/Base/ScriptContext.cpp:2550
#13 0x00007ffff33c4de9 in Js::ScriptContext::LoadScriptInternal (this=0x5555561af538, parser=0x7fffffffb9f0,
    script=0x55555617d5d0 "var NISLFuzzingFunc = function(p) {\n    if (!p) return;\n    var a = 0;\n    for (var h = 0;; ++h) {\n        for (var r = 0; r < 1; ++r) {\n", ' ' <repeats 12 times>, "a = r;\n        }\n    }\n};\nvar NISLParameter0 = fals"..., cb=286,
    pSrcInfo=0x7fffffffc5e0, pse=0x7fffffffc930, ppSourceInfo=0x7fffffffc5d8, rootDisplayName=0x7ffff43d3f80 <Js::Constants::GlobalCode> u"Global code", loadScriptFlag=(LoadScriptFlag_Utf8Source | LoadScriptFlag_ExternalArrayBuffer), scriptSource=0x7ff7f0b97000)
    at ~/ChakraCore-1.11.24/lib/Runtime/Base/ScriptContext.cpp:2488
#14 0x00007ffff33c5437 in Js::ScriptContext::LoadScript (this=0x5555561af538,
    script=0x55555617d5d0 "var NISLFuzzingFunc = function(p) {\n    if (!p) return;\n    var a = 0;\n    for (var h = 0;; ++h) {\n        for (var r = 0; r < 1; ++r) {\n", ' ' <repeats 12 times>, "a = r;\n        }\n    }\n};\nvar NISLParameter0 = fals"..., cb=286,
    pSrcInfo=0x7fffffffc5e0, pse=0x7fffffffc930, ppSourceInfo=0x7fffffffc5d8, rootDisplayName=0x7ffff43d3f80 <Js::Constants::GlobalCode> u"Global code", loadScriptFlag=(LoadScriptFlag_Utf8Source | LoadScriptFlag_ExternalArrayBuffer), scriptSource=0x7ff7f0b97000)
    at ~/ChakraCore-1.11.24/lib/Runtime/Base/ScriptContext.cpp:2526
#15 0x00007ffff2c81751 in RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86::operator()(Js::ScriptContext*, TTD::TTDJsRTActionResultAutoRecorder&) const (
    this=0x7fffffffc820, scriptContext=0x5555561af538, _actionEntryPopper=...) at ~/ChakraCore-1.11.24/lib/Jsrt/Jsrt.cpp:3538
#16 0x00007ffff2c81427 in _JsErrorCode ContextAPINoScriptWrapper<RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86>(RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86, bool, bool)::{lambda(Js::ScriptContext*)#1}::operator()(Js::ScriptContext*) const (this=0x7fffffffc7a8, scriptContext=0x5555561af538)
    at ~/ChakraCore-1.11.24/lib/Jsrt/JsrtInternal.h:316
#17 0x00007ffff2c80d2a in ContextAPINoScriptWrapper_Core<_JsErrorCode ContextAPINoScriptWrapper<RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86>(RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86, bool, bool)::{lambda(Js::ScriptContext*)#1}>(_JsErrorCode ContextAPINoScriptWrapper<RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86>(RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86, bool, bool)::{lambda(Js::ScriptContext*)#1}, bool, bool) (fn=..., allowInObjectBeforeCollectCallback=false, scriptExceptionAllowed=false) at ~/ChakraCore-1.11.24/lib/Jsrt/JsrtInternal.h:277
#18 0x00007ffff2c4b4b8 in ContextAPINoScriptWrapper<RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86>(RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**)::$_86, bool, bool) (fn=..., allowInObjectBeforeCollectCallback=false, scriptExceptionAllowed=false)
    at ~/ChakraCore-1.11.24/lib/Jsrt/JsrtInternal.h:314
#19 0x00007ffff2c4b35f in RunScriptCore (scriptSource=0x7ff7f0b97000,
    script=0x55555617d5d0 "var NISLFuzzingFunc = function(p) {\n    if (!p) return;\n    var a = 0;\n    for (var h = 0;; ++h) {\n        for (var r = 0; r < 1; ++r) {\n", ' ' <repeats 12 times>, "a = r;\n        }\n    }\n};\nvar NISLParameter0 = fals"..., cb=286,
    loadScriptFlag=(LoadScriptFlag_Utf8Source | LoadScriptFlag_ExternalArrayBuffer), sourceContext=0, sourceUrl=0x7ff7f0b70000 u"/home/nisl1/nisl8121/yw/TencentProject/result_analyse/crash/TestCase.js", parseOnly=false, parseAttributes=JsParseScriptAttributeNone,
    isSourceModule=false, result=0x0) at ~/ChakraCore-1.11.24/lib/Jsrt/Jsrt.cpp:3487
#20 0x00007ffff2c4deee in CompileRun (scriptVal=0x7ff7f0b97000, sourceContext=0, sourceUrl=0x7ff7f0bd5f00, parseAttributes=JsParseScriptAttributeNone, result=0x0, parseOnly=false)
    at ~/ChakraCore-1.11.24/lib/Jsrt/Jsrt.cpp:4991
#21 JsRun (scriptVal=0x7ff7f0b97000, sourceContext=0, sourceUrl=0x7ff7f0bd5f00, parseAttributes=JsParseScriptAttributeNone, result=0x0) at ~/ChakraCore-1.11.24/lib/Jsrt/Jsrt.cpp:5013
#22 0x000055555556045e in ChakraRTInterface::JsRun (script=0x7ff7f0b97000, sourceContext=0, sourceUrl=0x7ff7f0bd5f00, parseAttributes=JsParseScriptAttributeNone, result=0x0)
    at ~/ChakraCore-1.11.24/bin/ch/ChakraRtInterface.h:419
#23 0x000055555555d653 in RunScript (fileName=0x55555617c530 "./TestCase.js",
    fileContents=0x55555617d5d0 "var NISLFuzzingFunc = function(p) {\n    if (!p) return;\n    var a = 0;\n    for (var h = 0;; ++h) {\n        for (var r = 0; r < 1; ++r) {\n", ' ' <repeats 12 times>, "a = r;\n        }\n    }\n};\nvar NISLParameter0 = fals"...,
    fileLength=286, fileContentsFinalizeCallback=0x55555556c580 <WScriptJsrt::FinalizeFree(void*)>, bufferValue=0x0, fullPath=0x7fffffffd160 "/home/nisl1/nisl8121/yw/TencentProject/result_analyse/crash/TestCase.js", parserStateCache=0x0)
    at ~/ChakraCore-1.11.24/bin/ch/ch.cpp:479
#24 0x000055555555f0e1 in ExecuteTest (fileName=0x55555617c530 "./TestCase.js") at ~/ChakraCore-1.11.24/bin/ch/ch.cpp:913
#25 0x000055555555f1ac in ExecuteTestWithMemoryCheck (fileName=0x55555617c530 "./TestCase.js") at ~/ChakraCore-1.11.24/bin/ch/ch.cpp:963
#26 0x000055555555fa9b in main (argc=2, c_argv=0x7fffffffd5a8) at ~/ChakraCore-1.11.24/bin/ch/ch.cpp:1270

Using ASAN:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==8178==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x561fcd822a34 bp 0x7ffc3ac7b580 sp 0x7ffc3ac7b530 T0)
==8178==The signal is caused by a READ memory access.
==8178==Hint: address points to the zero page.
    #0 0x561fcd822a33 in EmitBooleanExpression(ParseNode*, int, int, ByteCodeGenerator*, FuncInfo*, bool, bool) (~/ChakraCore-1.11.24/out/Release/ch+0x177ea33)
    #1 0x561fcd8245b9 in ByteCodeGenerator::EmitInvertedLoop(ParseNodeLoop*, ParseNodeFor*, FuncInfo*) (~/ChakraCore-1.11.24/out/Release/ch+0x17805b9)
    #2 0x561fcd7ea583 in Emit(ParseNode*, ByteCodeGenerator*, FuncInfo*, int, bool, unsigned int, bool) (~/ChakraCore-1.11.24/out/Release/ch+0x1746583)
    #3 0x561fcd7e4275 in ByteCodeGenerator::EmitTopLevelStatement(ParseNode*, FuncInfo*, int) (~/ChakraCore-1.11.24/out/Release/ch+0x1740275)
    #4 0x561fcd800fa2 in ByteCodeGenerator::EmitFunctionBody(FuncInfo*) (~/ChakraCore-1.11.24/out/Release/ch+0x175cfa2)
    #5 0x561fcd806b76 in ByteCodeGenerator::EmitOneFunction(ParseNodeFnc*) (~/ChakraCore-1.11.24/out/Release/ch+0x1762b76)
    #6 0x561fcd8019ae in ByteCodeGenerator::EmitScopeList(ParseNode*, ParseNode*) (~/ChakraCore-1.11.24/out/Release/ch+0x175d9ae)
    #7 0x561fcd8016f6 in ByteCodeGenerator::EmitScopeList(ParseNode*, ParseNode*) (~/ChakraCore-1.11.24/out/Release/ch+0x175d6f6)
    #8 0x561fcd80199b in ByteCodeGenerator::EmitScopeList(ParseNode*, ParseNode*) (~/ChakraCore-1.11.24/out/Release/ch+0x175d99b)
    #9 0x561fcc7ef220 in ByteCodeGenerator::Generate(ParseNodeProg*, unsigned int, ByteCodeGenerator*, Js::ParseableFunctionInfo**, unsigned int, bool, Parser*, Js::ScriptFunction**) (~/ChakraCore-1.11.24/out/Release/ch+0x74b220)
    #10 0x561fcc7f5f31 in GenerateByteCode(ParseNodeProg*, unsigned int, Js::ScriptContext*, Js::ParseableFunctionInfo**, unsigned int, bool, Parser*, CompileScriptException*, Js::ScopeInfo*, Js::ScriptFunction**) (~/ChakraCore-1.11.24/out/Release/ch+0x751f31)
    #11 0x561fcc767a9e in Js::ScriptContext::LoadScriptInternal(Parser*, unsigned char const*, unsigned long, SRCINFO const*, CompileScriptException*, Js::Utf8SourceInfo**, char16_t const*, LoadScriptFlag, void*) (~/ChakraCore-1.11.24/out/Release/ch+0x6c3a9e)
    #12 0x561fcc76821f in Js::ScriptContext::LoadScript(unsigned char const*, unsigned long, SRCINFO const*, CompileScriptException*, Js::Utf8SourceInfo**, char16_t const*, LoadScriptFlag, void*) (~/ChakraCore-1.11.24/out/Release/ch+0x6c421f)
    #13 0x561fcc52a8ef in RunScriptCore(void*, unsigned char const*, unsigned long, LoadScriptFlag, unsigned long, char16_t const*, bool, _JsParseScriptAttributes, bool, void**) (~/ChakraCore-1.11.24/out/Release/ch+0x4868ef)
    #14 0x561fcc534cc5 in JsRun (~/ChakraCore-1.11.24/out/Release/ch+0x490cc5)
    #15 0x561fcc432002 in RunScript(char const*, char const*, unsigned long, void (*)(void*), void*, char*, void*) (~/ChakraCore-1.11.24/out/Release/ch+0x38e002)
    #16 0x561fcc434380 in ExecuteTest(char const*) (~/ChakraCore-1.11.24/out/Release/ch+0x390380)
    #17 0x561fcc435116 in main (~/ChakraCore-1.11.24/out/Release/ch+0x391116)
    #18 0x7f91738bac86 in __libc_start_main /build/glibc-uZu3wS/glibc-2.27/csu/../csu/libc-start.c:310
    #19 0x561fcc333a69 in _start (~/ChakraCore-1.11.24/out/Release/ch+0x28fa69)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (~/ChakraCore-1.11.24/out/Release/ch+0x177ea33) in EmitBooleanExpression(ParseNode*, int, int, ByteCodeGenerator*, FuncInfo*, bool, bool)
==8178==ABORTING
YiWen-y commented 2 years ago

I debugged this issue further using GBD, it appears to be a null pointer issue, here is the detailed debug info:

(gdb) set disassembly-flavor intel
(gdb) info r
rax            0x42     66
rbx            0x7fffffffb3d8   140737488335832
rcx            0x7fffffffb528   140737488336168
rdx            0x0      0
rsi            0x0      0
rdi            0x7fffffffb598   140737488336280
rbp            0x7fffffff9ba0   0x7fffffff9ba0
rsp            0x7fffffff9ad0   0x7fffffff9ad0
r8             0x7ff7f0b74800   140702872193024
r9             0x1      1
r10            0x0      0
r11            0x0      0
r12            0x7ffff43d3f80   140737291042688
r13            0x140    320
r14            0x7fffffffb9f0   140737488337392
r15            0x7fffffffc5d8   140737488340440
rip            0x7ffff34dcc75   0x7ffff34dcc75 <EmitBooleanExpression(ParseNode*, int, int, ByteCodeGenerator*, FuncInfo*, bool, bool)+229>
eflags         0x10206  [ PF IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
k0             0x0      0
k1             0x0      0
k2             0x0      0
k3             0x0      0
k4             0x0      0
k5             0x0      0
k6             0x0      0
k7             0x0      0
(gdb) x/i $pc
=> 0x7ffff34dcc75 <EmitBooleanExpression(ParseNode*, int, int, ByteCodeGenerator*, FuncInfo*, bool, bool)+229>: movzx  eax,BYTE PTR [rsi]

Combine the above stack information#0 0x00007ffff34dcc75 in EmitBooleanExpression (expr=0x0, trueLabel=10, falseLabel=4, byteCodeGenerator=0x7fffffffb4e0, funcInfo=0x7ff7f0b74800, trueFallthrough=true, falseFallthrough=false) at ~/ChakraCore-1.11.24/lib/Runtime/ByteCode/ByteCodeEmitter.cpp:8835, we can know that the pointer expr value is 0x0, so this is a null pointer problem.

ppenzin commented 2 years ago

This passes with development version.

AidPaike commented 1 year ago

This passes with development version.

Thanks for your reply. We tested the latest development version and found this bug has been fixed. I will close this issue soon :)

By the way, I have a few additional findngs summaried as follows: Firstly, I found this security bug has been exposed by a previous issue report #5532 back in 2018, and was quickly fixed. I just wonder why this bug still exits after fixed.

Secondly, through the detailed annalysis, I think this bug is caused due to the incomplete repair of #5332.