Skip to content

Commit 2e979ab

Browse files
committed
fix #362: Fix skipping of "repeat zero times" loops
1 parent 0acdf37 commit 2e979ab

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

src/engine/virtualmachine_p.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,15 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset)
264264
FREE_REGS(1);
265265
if (loopCount <= 0) {
266266
loopEnd = pos;
267-
while (*loopEnd != OP_LOOP_END)
267+
unsigned int loopCounter = 1;
268+
while ((*loopEnd != OP_LOOP_END) || (loopCounter > 0)) {
268269
loopEnd += instruction_arg_count[*loopEnd++];
270+
271+
if ((*loopEnd == OP_FOREVER_LOOP) || (*loopEnd == OP_REPEAT_LOOP) || (*loopEnd == OP_UNTIL_LOOP))
272+
loopCounter++;
273+
else if (*loopEnd == OP_LOOP_END)
274+
loopCounter--;
275+
}
269276
pos = loopEnd;
270277
} else {
271278
Loop l;
@@ -313,6 +320,7 @@ do_repeat_loop_index1 : {
313320
return pos;
314321

315322
do_loop_end : {
323+
assert(!loops.empty());
316324
Loop &l = loops.back();
317325
if (l.isRepeatLoop) {
318326
if ((l.index == -1) || (++l.index < l.max))

test/virtual_machine/virtual_machine_test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,3 +1602,17 @@ TEST(VirtualMachineTest, Reset)
16021602
vm.reset();
16031603
ASSERT_FALSE(vm.atEnd());
16041604
}
1605+
1606+
TEST(VirtualMachineTest, NoCrashWhenRepeatingZeroTimes)
1607+
{
1608+
// Regtest for #362
1609+
static unsigned int bytecode[] = { OP_START, OP_CONST, 0, OP_REPEAT_LOOP, OP_UNTIL_LOOP, OP_NULL, OP_BEGIN_UNTIL_LOOP, OP_LOOP_END, OP_LOOP_END, OP_HALT };
1610+
static Value constValues[] = { 0 };
1611+
1612+
EngineMock engineMock;
1613+
VirtualMachine vm(nullptr, &engineMock, nullptr);
1614+
vm.setBytecode(bytecode);
1615+
vm.setConstValues(constValues);
1616+
vm.run();
1617+
ASSERT_EQ(vm.registerCount(), 0);
1618+
}

0 commit comments

Comments
 (0)