summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsmatz <smatz@openttd.org>2009-07-13 11:09:02 +0000
committersmatz <smatz@openttd.org>2009-07-13 11:09:02 +0000
commitaa7bcb1259aef0c71523b9ccc945840edcf9c6b1 (patch)
tree5723d51f450d7021d1207fc55d4bb404c23d3e8d
parenta67f861d5505106ec8b919222da762ab7d185af6 (diff)
downloadopenttd-aa7bcb1259aef0c71523b9ccc945840edcf9c6b1.tar.xz
(svn r16808) -Fix (r16338): don't crash when loading savegame with invalid references
-rw-r--r--src/saveload/saveload.cpp36
1 files changed, 28 insertions, 8 deletions
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index 46c6104e6..54f2c451f 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -1135,6 +1135,8 @@ static void SlLoadChunks()
}
}
+static const char *_sl_ptrs_error; ///< error message if there was an error during fixing pointers, NULL otherwise
+
/** Fix all pointers (convert index -> pointer) */
static void SlFixPointers()
{
@@ -1142,6 +1144,7 @@ static void SlFixPointers()
const ChunkHandler * const *chsc;
_sl.action = SLA_PTRS;
+ _sl_ptrs_error = NULL;
DEBUG(sl, 1, "Fixing pointers");
@@ -1157,6 +1160,9 @@ static void SlFixPointers()
}
}
+ /* We need to fix all possible pointers even if there were invalid ones. This way pool cleaning will work fine. */
+ if (_sl_ptrs_error != NULL) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, _sl_ptrs_error);
+
DEBUG(sl, 1, "All pointers fixed");
assert(_sl.action == SLA_PTRS);
@@ -1520,41 +1526,55 @@ static void *IntToReference(size_t index, SLRefType rt)
switch (rt) {
case REF_ORDERLIST:
if (OrderList::IsValidID(index)) return OrderList::Get(index);
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid OrderList");
+ _sl_ptrs_error = "Referencing invalid OrderList";
+ break;
case REF_ORDER:
if (Order::IsValidID(index)) return Order::Get(index);
/* in old versions, invalid order was used to mark end of order list */
if (CheckSavegameVersionOldStyle(5, 2)) return NULL;
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Order");
+ _sl_ptrs_error = "Referencing invalid Order";
+ break;
case REF_VEHICLE_OLD:
case REF_VEHICLE:
if (Vehicle::IsValidID(index)) return Vehicle::Get(index);
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Vehicle");
+ _sl_ptrs_error = "Referencing invalid Vehicle";
+ break;
case REF_STATION:
if (Station::IsValidID(index)) return Station::Get(index);
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Station");
+ _sl_ptrs_error = "Referencing invalid Station";
+ break;
case REF_TOWN:
if (Town::IsValidID(index)) return Town::Get(index);
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Town");
+ _sl_ptrs_error = "Referencing invalid Town";
+ break;
case REF_ROADSTOPS:
if (RoadStop::IsValidID(index)) return RoadStop::Get(index);
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid RoadStop");
+ _sl_ptrs_error = "Referencing invalid RoadStop";
+ break;
case REF_ENGINE_RENEWS:
if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index);
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid EngineRenew");
+ _sl_ptrs_error = "Referencing invalid EngineRenew";
+ break;
case REF_CARGO_PACKET:
if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index);
- SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid CargoPacket");
+ _sl_ptrs_error = "Referencing invalid CargoPacket";
+ break;
default: NOT_REACHED();
}
+
+ /* Print a debug message about each invalid reference */
+ DEBUG(sl, 1, "%s (index = " PRINTF_SIZE ")", _sl_ptrs_error, index);
+
+ /* Return NULL for broken savegames */
+ return NULL;
}
/** The format for a reader/writer type of a savegame */