aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-01-31 19:03:33 -0600
committerColin Snover2017-03-30 20:49:37 -0500
commitee644ec01b292c3308085170021f04f6f6917bc9 (patch)
tree8c36e03eadd759ecdb994d9bc211ac20cd57f942
parent3678390f3eac8d8373840c91646076154f49aed1 (diff)
downloadscummvm-rg350-ee644ec01b292c3308085170021f04f6f6917bc9.tar.gz
scummvm-rg350-ee644ec01b292c3308085170021f04f6f6917bc9.tar.bz2
scummvm-rg350-ee644ec01b292c3308085170021f04f6f6917bc9.zip
SCI32: Check for game aborts in all kList iteration methods
This fixes a use-after-free in GK2 when restoring a second save game, when the List reg_t is still considered valid but the List has moved due to a partial game restore.
-rw-r--r--engines/sci/engine/klists.cpp13
1 files changed, 13 insertions, 0 deletions
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index 305d459ac1..2f66e51a6e 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -618,6 +618,7 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) {
}
} else {
invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
+
// Check if the call above leads to a game restore, in which case
// the segment manager will be reset, and the original list will
// be invalidated
@@ -672,6 +673,12 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) {
} else {
invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
+ // Check if the call above leads to a game restore, in which case
+ // the segment manager will be reset, and the original list will
+ // be invalidated
+ if (s->abortScriptProcessing == kAbortLoadGame)
+ return s->r_acc;
+
// Check if the result is true
if (!s->r_acc.isNull()) {
s->r_acc = curObject;
@@ -721,6 +728,12 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {
s->r_acc = readSelector(s->_segMan, curObject, slc);
} else {
invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
+
+ // Check if the call above leads to a game restore, in which case
+ // the segment manager will be reset, and the original list will
+ // be invalidated
+ if (s->abortScriptProcessing == kAbortLoadGame)
+ return s->r_acc;
}
// Check if the result isn't true