From 3daf4d012bf16de42ef528419f7a224ff8f54d5e Mon Sep 17 00:00:00 2001 From: rubidium Date: Tue, 4 Oct 2011 20:15:50 +0000 Subject: [PATCH] (svn r22993) [1.1] -Backport from trunk: - Fix: The savegame description and loading of savegames would crash with savegames from a patched stable (which did not bump the savegame version) [FS#4778] (r22958, r22957) - Fix: Guard from reading outside the silly name list (r22955) - Fix: [NewGRF] Properly limit the length of strings in a choice list (r22952) - Fix: [NewGRF] Do not call CB 32 for disaster, effect vehicles or aircraft shadows/rotors (r22947) --- src/company_cmd.cpp | 2 +- src/newgrf_text.cpp | 4 +++- src/saveload/company_sl.cpp | 10 ++++++++-- src/saveload/strings_sl.cpp | 4 ++-- src/saveload/town_sl.cpp | 4 ++++ src/strings.cpp | 2 +- src/strings_type.h | 13 ++++--------- src/vehicle.cpp | 17 ++++++++++++++++- src/vehicle_base.h | 1 + 9 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index d8d52ecd6d..6fcedaf94a 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -349,7 +349,7 @@ static void GenerateCompanyName(Company *c) StringID str; uint32 strp; if (t->name == NULL && IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1)) { - str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_PLAYERNAME_START; + str = t->townnametype - SPECSTR_TOWNNAME_START + SPECSTR_COMPANY_NAME_START; strp = t->townnameparts; verify_name:; diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp index edf8662338..a4de993998 100644 --- a/src/newgrf_text.cpp +++ b/src/newgrf_text.cpp @@ -371,7 +371,9 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator { for (int i = 0; i < count; i++) { int idx = (this->type == SCC_GENDER_LIST ? lm->GetReverseMapping(i, true) : i + 1); const char *str = this->strings[this->strings.Contains(idx) ? idx : 0]; - size_t len = strlen(str); + /* Limit the length of the string we copy to 0xFE. The length is written above + * as a byte and we need room for the final '\0'. */ + size_t len = min(0xFE, strlen(str)); memcpy(d, str, len); d += len; *d++ = '\0'; diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 2684a06559..894611d6e4 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -349,8 +349,7 @@ static void Check_PLYR() SaveLoad_PLYR_common(NULL, cprops); /* We do not load old custom names */ - if (IsSavegameVersionBefore(84)) - { + if (IsSavegameVersionBefore(84)) { if (GB(cprops->name_1, 11, 5) == 15) { cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; } @@ -360,6 +359,13 @@ static void Check_PLYR() } } + if (cprops->name == NULL && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) && + cprops->name_1 != STR_GAME_SAVELOAD_NOT_AVAILABLE && cprops->name_1 != STR_SV_UNNAMED && + cprops->name_1 != SPECSTR_ANDCO_NAME && cprops->name_1 != SPECSTR_PRESIDENT_NAME && + cprops->name_1 != SPECSTR_SILLY_NAME) { + cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE; + } + if (!_load_check_data.companies.Insert(index, cprops)) delete cprops; } } diff --git a/src/saveload/strings_sl.cpp b/src/saveload/strings_sl.cpp index 8ff5591cbe..aaf2d32cd9 100644 --- a/src/saveload/strings_sl.cpp +++ b/src/saveload/strings_sl.cpp @@ -29,8 +29,8 @@ StringID RemapOldStringID(StringID s) switch (s) { case 0x0006: return STR_SV_EMPTY; case 0x7000: return STR_SV_UNNAMED; - case 0x70E4: return SPECSTR_PLAYERNAME_ENGLISH; - case 0x70E9: return SPECSTR_PLAYERNAME_ENGLISH; + case 0x70E4: return SPECSTR_COMPANY_NAME_START; + case 0x70E9: return SPECSTR_COMPANY_NAME_START; case 0x8864: return STR_SV_TRAIN_NAME; case 0x902B: return STR_SV_ROAD_VEHICLE_NAME; case 0x9830: return STR_SV_SHIP_NAME; diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index e246f61f7f..970cc5bd4e 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -204,6 +204,10 @@ static void Load_TOWN() while ((index = SlIterateArray()) != -1) { Town *t = new (index) Town(); SlObject(t, _town_desc); + + if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST)) { + SlErrorCorrupt("Invalid town name generator"); + } } } diff --git a/src/strings.cpp b/src/strings.cpp index 36f67d7420..6aa3d013eb 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1413,7 +1413,7 @@ static char *GetSpecialNameString(char *buff, int ind, int64 *argv, const int64 { switch (ind) { case 1: // not used - return strecpy(buff, _silly_company_names[GetInt32(&argv, argve, &argt) & 0xFFFF], last); + return strecpy(buff, _silly_company_names[min(GetInt32(&argv, argve, &argt) & 0xFFFF, lengthof(_silly_company_names) - 1)], last); case 2: // used for Foobar & Co company names return GenAndCoName(buff, GetInt32(&argv, argve, &argt), last); diff --git a/src/strings_type.h b/src/strings_type.h index 1dea474f91..35f22e5fc2 100644 --- a/src/strings_type.h +++ b/src/strings_type.h @@ -54,16 +54,11 @@ enum SpecialStrings { SPECSTR_TOWNNAME_CATALAN, SPECSTR_TOWNNAME_LAST = SPECSTR_TOWNNAME_CATALAN, - /* special strings for player names on the form "TownName transport". */ - SPECSTR_PLAYERNAME_START = 0x70EA, - SPECSTR_PLAYERNAME_ENGLISH = SPECSTR_PLAYERNAME_START, - SPECSTR_PLAYERNAME_FRENCH, - SPECSTR_PLAYERNAME_GERMAN, - SPECSTR_PLAYERNAME_AMERICAN, - SPECSTR_PLAYERNAME_LATIN, - SPECSTR_PLAYERNAME_SILLY, - SPECSTR_PLAYERNAME_LAST = SPECSTR_PLAYERNAME_SILLY, + /* special strings for company names on the form "TownName transport". */ + SPECSTR_COMPANY_NAME_START = 0x70EA, + SPECSTR_COMPANY_NAME_LAST = SPECSTR_COMPANY_NAME_START + SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START, + SPECSTR_SILLY_NAME = 0x70E5, SPECSTR_ANDCO_NAME = 0x70E6, SPECSTR_PRESIDENT_NAME = 0x70E7, diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 58246a6b09..0ed2475d86 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -634,6 +634,21 @@ bool Vehicle::IsEngineCountable() const } } +/** + * Check whether Vehicle::engine_type has any meaning. + * @return true if the vehicle has a useable engine type. + */ +bool Vehicle::HasEngineType() const +{ + switch (this->type) { + case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft(); + case VEH_TRAIN: + case VEH_ROAD: + case VEH_SHIP: return true; + default: return false; + } +} + /** * Handle the pathfinding result, especially the lost status. * If the vehicle is now lost and wasn't previously fire an @@ -784,7 +799,7 @@ static void RunVehicleDayProc() if (v == NULL) continue; /* Call the 32-day callback if needed */ - if ((v->day_counter & 0x1F) == 0) { + if ((v->day_counter & 0x1F) == 0 && v->HasEngineType()) { uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v); if (callback != CALLBACK_FAILED) { if (HasBit(callback, 0)) TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10 diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 4f4547f34d..7b0a8c214b 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -701,6 +701,7 @@ public: } bool IsEngineCountable() const; + bool HasEngineType() const; bool HasDepotOrder() const; void HandlePathfindingResult(bool path_found);