diff options
author | md5 | 2011-02-22 18:52:44 +0200 |
---|---|---|
committer | md5 | 2011-02-22 18:52:44 +0200 |
commit | cf904b1156091c65486bf3124e3ef1d3fd1b6f8f (patch) | |
tree | b85b6b1db6d5af1c88e59d779214fae7c1e66eb0 /engines/sci/engine | |
parent | 07c054d6c63bec5a9abd1b77781958f4a83969bc (diff) | |
download | scummvm-rg350-cf904b1156091c65486bf3124e3ef1d3fd1b6f8f.tar.gz scummvm-rg350-cf904b1156091c65486bf3124e3ef1d3fd1b6f8f.tar.bz2 scummvm-rg350-cf904b1156091c65486bf3124e3ef1d3fd1b6f8f.zip |
SCI: Added code to aid in detecting infinite loops in scripts
When the ABORT_ON_INFINITE_LOOP define is defined in vm.cpp, the VM will now
abort in cases where a conditional statement is followed by an unconditional
jump (which will most likely lead to an infinite loop). Aids in detecting
infinite loop bugs such as #3040722.
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/vm.cpp | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a70ff5ab72..43d38a4979 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -47,6 +47,10 @@ const reg_t NULL_REG = {0, 0}; const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; const reg_t TRUE_REG = {0, 1}; //#define VM_DEBUG_SEND +// Enable the define below to have the VM abort on cases where a conditional +// statement is followed by an unconditional jump (which will most likely lead +// to an infinite loop). Aids in detecting script bugs such as #3040722. +//#define ABORT_ON_INFINITE_LOOP #define SCI_XS_CALLEE_LOCALS ((SegmentId)-1) @@ -871,6 +875,10 @@ void run_vm(EngineState *s) { s->_executionStackPosChanged = true; // Force initialization +#ifdef ABORT_ON_INFINITE_LOOP + byte prevOpcode = 0xFF; +#endif + while (1) { int var_type; // See description below int var_number; @@ -935,7 +943,22 @@ void run_vm(EngineState *s) { byte extOpcode; s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams); const byte opcode = extOpcode >> 1; - //debug("%s: %d, %d, %d, %d, acc = %04x:%04x", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc)); + //debug("%s: %d, %d, %d, %d, acc = %04x:%04x, script %d, local script %d", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc), scr->getScriptNumber(), local_script->getScriptNumber()); + +#ifdef ABORT_ON_INFINITE_LOOP + if (prevOpcode != 0xFF) { + if (prevOpcode == op_eq_ || prevOpcode == op_ne_ || + prevOpcode == op_gt_ || prevOpcode == op_ge_ || + prevOpcode == op_lt_ || prevOpcode == op_le_ || + prevOpcode == op_ugt_ || prevOpcode == op_uge_ || + prevOpcode == op_ult_ || prevOpcode == op_ule_) { + if (opcode == op_jmp) + error("Infinite loop detected in script %d", scr->getScriptNumber()); + } + } + + prevOpcode = opcode; +#endif switch (opcode) { |