aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorFilippos Karapetis2011-11-28 22:35:10 +0200
committerFilippos Karapetis2011-11-28 22:36:58 +0200
commit381e92a576ef05de60c1a90d534785ebd7a112c2 (patch)
tree903d7c95b2d96d82a3d1faabb5cf0ae3b7191597 /engines/sci
parent29fb48b74b64752b712c2b0b2a15f6ff7dd33716 (diff)
downloadscummvm-rg350-381e92a576ef05de60c1a90d534785ebd7a112c2.tar.gz
scummvm-rg350-381e92a576ef05de60c1a90d534785ebd7a112c2.tar.bz2
scummvm-rg350-381e92a576ef05de60c1a90d534785ebd7a112c2.zip
SCI: Added handling of invalid jump offsets (e.g. QFG2, script 260)
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp3
-rw-r--r--engines/sci/engine/scriptdebug.cpp10
-rw-r--r--engines/sci/engine/vm.cpp12
3 files changed, 22 insertions, 3 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index b852de74a9..571d2f834b 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -2978,7 +2978,8 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
// there is a jump after a ret, we don't stop processing
if (opcode == op_bt || opcode == op_bnt || opcode == op_jmp) {
uint16 curJmpOffset = offset + (uint16)opparams[0];
- if (curJmpOffset > maxJmpOffset)
+ // QFG2 has invalid jumps outside the script buffer in script 260
+ if (curJmpOffset > maxJmpOffset && curJmpOffset < script->getScriptSize())
maxJmpOffset = curJmpOffset;
}
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index ad3f4fb788..3faa13183c 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -296,7 +296,7 @@ bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) {
Script *script_entity = (Script *)mobj;
const byte *scr = script_entity->getBuf();
- int scr_size = script_entity->getBufSize();
+ int scr_size = script_entity->getScriptSize();
if (pos.offset >= scr_size)
return false;
@@ -310,7 +310,13 @@ bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) {
case op_bt:
case op_bnt:
case op_jmp:
- jumpTarget = pos + bytecount + opparams[0];
+ {
+ reg_t jmpTarget = pos + bytecount + opparams[0];
+ // QFG2 has invalid jumps outside the script buffer in script 260
+ if (jmpTarget.offset >= scr_size)
+ return false;
+ jumpTarget = jmpTarget;
+ }
return true;
default:
return false;
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 6b3a3198ea..226a73b139 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -764,16 +764,28 @@ void run_vm(EngineState *s) {
// Branch relative if true
if (s->r_acc.offset || s->r_acc.segment)
s->xs->addr.pc.offset += opparams[0];
+
+ if (s->xs->addr.pc.offset >= local_script->getScriptSize())
+ error("[VM] op_bt: request to jump past the end of script %d (offset %d, script is %d bytes)",
+ local_script->getScriptNumber(), s->xs->addr.pc.offset, local_script->getScriptSize());
break;
case op_bnt: // 0x18 (24)
// Branch relative if not true
if (!(s->r_acc.offset || s->r_acc.segment))
s->xs->addr.pc.offset += opparams[0];
+
+ if (s->xs->addr.pc.offset >= local_script->getScriptSize())
+ error("[VM] op_bnt: request to jump past the end of script %d (offset %d, script is %d bytes)",
+ local_script->getScriptNumber(), s->xs->addr.pc.offset, local_script->getScriptSize());
break;
case op_jmp: // 0x19 (25)
s->xs->addr.pc.offset += opparams[0];
+
+ if (s->xs->addr.pc.offset >= local_script->getScriptSize())
+ error("[VM] op_jmp: request to jump past the end of script %d (offset %d, script is %d bytes)",
+ local_script->getScriptNumber(), s->xs->addr.pc.offset, local_script->getScriptSize());
break;
case op_ldi: // 0x1a (26)