diff options
Diffstat (limited to 'src/saveload/saveload.cpp')
-rw-r--r-- | src/saveload/saveload.cpp | 57 |
1 files changed, 35 insertions, 22 deletions
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index ba2178717..903892faf 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -387,6 +387,19 @@ static void NORETURN SlError(StringID string, const char *extra_msg = NULL) throw std::exception(); } +/** + * Error handler for corrupt savegames. Sets everything up to show the + * error message and to clean up the mess of a partial savegame load. + * @param msg Location the corruption has been spotted. + * @note This function does never return as it throws an exception to + * break out of all the saveload code. + */ +void NORETURN SlErrorCorrupt(const char *msg) +{ + SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, msg); +} + + typedef void (*AsyncSaveFinishProc)(); ///< Callback for when the savegame loading is finished. static AsyncSaveFinishProc _async_save_finish = NULL; ///< Callback to call when the savegame loading is finished. static ThreadObject *_save_thread; ///< The thread we're using to compress and write a savegame @@ -427,7 +440,7 @@ void ProcessAsyncSaveFinish() static void SlReadFill() { size_t len = _sl.read_bytes(); - if (len == 0) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected end of chunk"); + if (len == 0) SlErrorCorrupt("Unexpected end of chunk"); _sl.bufp = _sl.buf; _sl.bufe = _sl.buf + len; @@ -553,7 +566,7 @@ static uint SlReadSimpleGamma() if (HasBit(i, 5)) { i &= ~0x20; if (HasBit(i, 4)) { - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unsupported gamma"); + SlErrorCorrupt("Unsupported gamma"); } i = (i << 8) | SlReadByte(); } @@ -688,7 +701,7 @@ int SlIterateArray() /* After reading in the whole array inside the loop * we must have read in all the data, so we must be at end of current block. */ - if (_next_offs != 0 && SlGetOffs() != _next_offs) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size"); + if (_next_offs != 0 && SlGetOffs() != _next_offs) SlErrorCorrupt("Invalid chunk size"); while (true) { uint length = SlReadArrayLength(); @@ -1136,38 +1149,38 @@ 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"); + SlErrorCorrupt("Referencing invalid OrderList"); 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"); + SlErrorCorrupt("Referencing invalid Order"); 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"); + SlErrorCorrupt("Referencing invalid Vehicle"); case REF_STATION: if (Station::IsValidID(index)) return Station::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Station"); + SlErrorCorrupt("Referencing invalid Station"); case REF_TOWN: if (Town::IsValidID(index)) return Town::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid Town"); + SlErrorCorrupt("Referencing invalid Town"); case REF_ROADSTOPS: if (RoadStop::IsValidID(index)) return RoadStop::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid RoadStop"); + SlErrorCorrupt("Referencing invalid RoadStop"); case REF_ENGINE_RENEWS: if (EngineRenew::IsValidID(index)) return EngineRenew::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid EngineRenew"); + SlErrorCorrupt("Referencing invalid EngineRenew"); case REF_CARGO_PACKET: if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index); - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Referencing invalid CargoPacket"); + SlErrorCorrupt("Referencing invalid CargoPacket"); default: NOT_REACHED(); } @@ -1441,7 +1454,7 @@ void SlAutolength(AutolengthProc *proc, void *arg) /* And write the stuff */ proc(arg); - if (offs != SlGetOffs()) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size"); + if (offs != SlGetOffs()) SlErrorCorrupt("Invalid chunk size"); } /** @@ -1473,9 +1486,9 @@ static void SlLoadChunk(const ChunkHandler *ch) _sl.obj_len = len; endoffs = SlGetOffs() + len; ch->load_proc(); - if (SlGetOffs() != endoffs) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size"); + if (SlGetOffs() != endoffs) SlErrorCorrupt("Invalid chunk size"); } else { - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk type"); + SlErrorCorrupt("Invalid chunk type"); } break; } @@ -1523,9 +1536,9 @@ static void SlLoadCheckChunk(const ChunkHandler *ch) } else { SlSkipBytes(len); } - if (SlGetOffs() != endoffs) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk size"); + if (SlGetOffs() != endoffs) SlErrorCorrupt("Invalid chunk size"); } else { - SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Invalid chunk type"); + SlErrorCorrupt("Invalid chunk type"); } break; } @@ -1632,7 +1645,7 @@ static void SlLoadChunks() DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id); ch = SlFindChunkHandler(id); - if (ch == NULL) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unknown chunk type"); + if (ch == NULL) SlErrorCorrupt("Unknown chunk type"); SlLoadChunk(ch); } } @@ -1647,7 +1660,7 @@ static void SlLoadCheckChunks() DEBUG(sl, 2, "Loading chunk %c%c%c%c", id >> 24, id >> 16, id >> 8, id); ch = SlFindChunkHandler(id); - if (ch == NULL) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unknown chunk type"); + if (ch == NULL) SlErrorCorrupt("Unknown chunk type"); SlLoadCheckChunk(ch); } } @@ -1700,13 +1713,13 @@ static size_t ReadLZO() size = TO_BE32(size); } - if (size >= sizeof(out)) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Inconsistent size"); + if (size >= sizeof(out)) SlErrorCorrupt("Inconsistent size"); /* Read block */ if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE); /* Verify checksum */ - if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Bad checksum"); + if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlErrorCorrupt("Bad checksum"); /* Decompress */ lzo1x_decompress(out + sizeof(uint32) * 1, size, _sl.buf, &len, NULL); @@ -2099,7 +2112,7 @@ static SaveOrLoadResult SaveFileToDisk(bool threaded) uint i = 0; size_t t = _ts.count; - if (_ts.count != _sl.offs_base) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected size of chunk"); + if (_ts.count != _sl.offs_base) SlErrorCorrupt("Unexpected size of chunk"); while (t >= MEMORY_CHUNK_SIZE) { _sl.buf = _memory_savegame[i++]; fmt->writer(MEMORY_CHUNK_SIZE); @@ -2116,7 +2129,7 @@ static SaveOrLoadResult SaveFileToDisk(bool threaded) } fmt->uninit_write(); - if (_ts.count != _sl.offs_base) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Unexpected size of chunk"); + if (_ts.count != _sl.offs_base) SlErrorCorrupt("Unexpected size of chunk"); UnInitMem(); fclose(_sl.fh); |