Skip to content

Commit 07271b9

Browse files
committed
[MERGE #5655 @wyrichte] Fixes #5532 null pointer dereference in EmitBooleanExpression
Merge pull request #5655 from wyrichte:bug_5532 Fixes #5532 Given a nested for loop that qualifies for loop inversion, the lack of a conditional in the outer loop causes a read access violation when the conditional’s ParseNode’s nop is read. The conditional is analyzed to perform a zero trip test which can skip the execution of the loop entirely. In the case where the outer loop lacks a conditional, the zero trip test will not pass. Therefore when the outer loop lacks a conditional skipping the inclusion of a zero trip test is valid and avoids the read access violation.
2 parents 9ef5b63 + 95c41a5 commit 07271b9

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

lib/Runtime/ByteCode/ByteCodeEmitter.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9259,12 +9259,16 @@ void ByteCodeGenerator::EmitInvertedLoop(ParseNodeLoop* outerLoop, ParseNodeFor*
92599259
this->m_writer.Br(afterInvertedLoop);
92609260
this->m_writer.MarkLabel(invertedLoopLabel);
92619261

9262-
// Emit a zero trip test for the original outer-loop
9263-
Js::ByteCodeLabel zeroTrip = this->m_writer.DefineLabel();
9264-
ParseNode* testNode = this->GetParser()->CopyPnode(outerLoop->AsParseNodeFor()->pnodeCond);
9265-
EmitBooleanExpression(testNode, zeroTrip, afterInvertedLoop, this, funcInfo, true, false);
9266-
this->m_writer.MarkLabel(zeroTrip);
9267-
funcInfo->ReleaseLoc(testNode);
9262+
// Emit a zero trip test for the original outer-loop if the outer-loop
9263+
// has a condition
9264+
if (outerLoop->AsParseNodeFor()->pnodeCond)
9265+
{
9266+
Js::ByteCodeLabel zeroTrip = this->m_writer.DefineLabel();
9267+
ParseNode* testNode = this->GetParser()->CopyPnode(outerLoop->AsParseNodeFor()->pnodeCond);
9268+
EmitBooleanExpression(testNode, zeroTrip, afterInvertedLoop, this, funcInfo, true, false);
9269+
this->m_writer.MarkLabel(zeroTrip);
9270+
funcInfo->ReleaseLoc(testNode);
9271+
}
92689272

92699273
// emit inverted
92709274
Emit(invertedLoop->pnodeInit, this, funcInfo, false);

test/loop/loopinversion.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,10 @@ function g5()
7070
};
7171
g5();
7272

73+
// Tests that loop inversion does not crash when the outer loop does not have
74+
// a condition. In order to not stay in an infinite loop, these functions return
75+
// immediately. The bytecode will still be generated.
76+
function g6(p){if(!p) return; var a = 0; for (var h = 0;; ++h){ for (var r = 0; r < 1; ++r){ a = r; }}};g6(0);
77+
function g6a(p){"use strict"; if(!p) return; var a = 0; for (var h = 0;; ++h){ for (var r = 0; r < 1; ++r){ a = r; }}};g6a(0);
7378

7479
WScript.Echo("pass");

0 commit comments

Comments
 (0)