From aa7bcb1259aef0c71523b9ccc945840edcf9c6b1 Mon Sep 17 00:00:00 2001 From: smatz Date: Mon, 13 Jul 2009 11:09:02 +0000 Subject: (svn r16808) -Fix (r16338): don't crash when loading savegame with invalid references --- src/saveload/saveload.cpp | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'src/saveload/saveload.cpp') 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 */ -- cgit v1.2.3-54-g00ecf