Skip to content

Commit 18a3824

Browse files
committed
fix #378: Skip loops in if statements correctly
1 parent 241dfc1 commit 18a3824

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

src/engine/virtualmachine_p.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,15 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset)
239239
do_if:
240240
if (!READ_LAST_REG()->toBool()) {
241241
unsigned int ifCounter = 1;
242-
while ((*pos != OP_ELSE && *pos != OP_ENDIF) || (ifCounter > 0)) {
242+
while (!((*pos == OP_ELSE && ifCounter == 1) || (*pos == OP_ENDIF && ifCounter == 0))) {
243243
pos += instruction_arg_count[*pos++];
244244

245-
if (*pos == OP_IF)
245+
if ((*pos == OP_IF) || (*pos == OP_FOREVER_LOOP) || (*pos == OP_REPEAT_LOOP) || (*pos == OP_UNTIL_LOOP))
246246
ifCounter++;
247-
else if ((*pos == OP_ELSE) || (*pos == OP_ENDIF))
247+
else if ((*pos == OP_ENDIF) || (*pos == OP_LOOP_END)) {
248+
assert(ifCounter > 0);
248249
ifCounter--;
250+
}
249251
}
250252
}
251253
FREE_REGS(1);
@@ -275,10 +277,12 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset)
275277
while ((*loopEnd != OP_LOOP_END) || (loopCounter > 0)) {
276278
loopEnd += instruction_arg_count[*loopEnd++];
277279

278-
if ((*loopEnd == OP_FOREVER_LOOP) || (*loopEnd == OP_REPEAT_LOOP) || (*loopEnd == OP_UNTIL_LOOP))
280+
if ((*loopEnd == OP_IF) || (*loopEnd == OP_FOREVER_LOOP) || (*loopEnd == OP_REPEAT_LOOP) || (*loopEnd == OP_UNTIL_LOOP))
279281
loopCounter++;
280-
else if (*loopEnd == OP_LOOP_END)
282+
else if ((*loopEnd == OP_ENDIF) || (*loopEnd == OP_LOOP_END)) {
283+
assert(loopCounter > 0);
281284
loopCounter--;
285+
}
282286
}
283287
pos = loopEnd;
284288
} else {

test/virtual_machine/virtual_machine_test.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,3 +1626,14 @@ TEST(VirtualMachineTest, NoCrashInNestedIfStatementsWithLoop)
16261626
vm.run();
16271627
ASSERT_EQ(vm.registerCount(), 0);
16281628
}
1629+
1630+
TEST(VirtualMachineTest, NoCrashInNestedIfStatementsWithLoopAndIfElse)
1631+
{
1632+
// Regtest for #378
1633+
static unsigned int bytecode[] = { OP_START, OP_NULL, OP_IF, OP_NULL, OP_REPEAT_LOOP, OP_NULL, OP_IF, OP_ELSE, OP_ENDIF, OP_LOOP_END, OP_ENDIF, OP_HALT };
1634+
1635+
VirtualMachine vm(nullptr, nullptr, nullptr);
1636+
vm.setBytecode(bytecode);
1637+
vm.run();
1638+
ASSERT_EQ(vm.registerCount(), 0);
1639+
}

0 commit comments

Comments
 (0)