(svn r22025) -Fix: verify there is enough space in the pool when creating new pool items while loading old savegames

This commit is contained in:
smatz 2011-02-08 18:34:13 +00:00
parent 364ef8e6e6
commit 887a7724dc
6 changed files with 38 additions and 4 deletions

View File

@ -497,6 +497,9 @@ void SetCachedEngineCounts()
}
}
/**
* Initialise the engine pool with the data from the original vehicles.
*/
void SetupEngines()
{
DeleteWindowByClass(WC_ENGINE_PREVIEW);
@ -506,6 +509,9 @@ void SetupEngines()
const EngineIDMapping *end = _engine_mngr.End();
uint index = 0;
for (const EngineIDMapping *eid = _engine_mngr.Begin(); eid != end; eid++, index++) {
/* Assert is safe; there won't be more than 256 original vehicles
* in any case, and we just cleaned the pool. */
assert(Engine::CanAllocateItem());
const Engine *e = new Engine(eid->type, eid->internal_id);
assert(e->index == index);
}

View File

@ -782,11 +782,18 @@ bool AfterLoadGame()
case STATION_TRUCK:
case STATION_BUS:
if (IsSavegameVersionBefore(6)) {
/* Before version 5 you could not have more than 250 stations.
* Version 6 adds large maps, so you could only place 253*253
* road stops on a map (no freeform edges) = 64009. So, yes
* someone could in theory create such a full map to trigger
* this assertion, it's safe to assume that's only something
* theoretical and does not happen in normal games. */
assert(RoadStop::CanAllocateItem());
/* From this version on there can be multiple road stops of the
* same type per station. Convert the existing stops to the new
* internal data structure. */
RoadStop *rs = new RoadStop(t);
if (rs == NULL) error("Too many road stops in savegame");
RoadStop **head =
IsTruckStop(t) ? &st->truck_stops : &st->bus_stops;
@ -1928,6 +1935,12 @@ bool AfterLoadGame()
ObjectType type = GetObjectType(t);
int size = type == OBJECT_HQ ? 2 : 1;
if (!Object::CanAllocateItem()) {
/* Nice... you managed to place 64k lighthouses and
* antennae on the map... boohoo. */
SlError(STR_ERROR_TOO_MANY_OBJECTS);
}
Object *o = new Object();
o->location.tile = t;
o->location.w = size;
@ -2024,6 +2037,10 @@ bool AfterLoadGame()
FOR_ALL_STATIONS(st) {
std::list<Vehicle *>::iterator iter;
for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
/* There are always as many CargoPayments as Vehicles. We need to make the
* assert() in Pool::GetNew() happy by calling CanAllocateItem(). */
assert_compile(CargoPaymentPool::MAX_SIZE == VehiclePool::MAX_SIZE);
assert(CargoPayment::CanAllocateItem());
Vehicle *v = *iter;
if (v->cargo_payment == NULL) v->cargo_payment = new CargoPayment(v);
}

View File

@ -472,7 +472,7 @@ static void SlNullPointers()
* @note This function does never return as it throws an exception to
* break out of all the saveload code.
*/
static void NORETURN SlError(StringID string, const char *extra_msg = NULL)
void NORETURN SlError(StringID string, const char *extra_msg)
{
/* Distinguish between loading into _load_check_data vs. normal save/load. */
if (_sl.action == SLA_LOAD_CHECK) {

View File

@ -13,6 +13,7 @@
#define SAVELOAD_H
#include "../fileio_type.h"
#include "../strings_type.h"
#ifdef SIZE_MAX
#undef SIZE_MAX
@ -539,6 +540,7 @@ void SlGlobList(const SaveLoadGlobVarList *sldg);
void SlArray(void *array, size_t length, VarType conv);
void SlObject(void *object, const SaveLoad *sld);
bool SlObjectMember(void *object, const SaveLoad *sld);
void NORETURN SlError(StringID string, const char *extra_msg = NULL);
void NORETURN SlErrorCorrupt(const char *msg);
bool SaveloadCrashWithMissingNewGRFs();

View File

@ -284,7 +284,11 @@ static void Load_STNS()
/* In old versions, enroute_from used 0xFF as INVALID_STATION */
StationID source = (IsSavegameVersionBefore(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
/* Don't construct the packet with station here, because that'll fail with old savegames */
/* Make sure we can allocate the CargoPacket. This is safe
* as there can only be ~64k stations and 32 cargos in these
* savegame versions. As the CargoPacketPool has more than
* 16 million entries; it fits by an order of magnitude. */
assert(CargoPacket::CanAllocateItem());
ge->cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, source, _cargo_source_xy, _cargo_source_xy, _cargo_feeder_share));
SB(ge->acceptance_pickup, GoodsEntry::PICKUP, 1, 1);
}

View File

@ -270,6 +270,11 @@ void AfterLoadVehicles(bool part_of_load)
if (IsSavegameVersionBefore(105)) { // Pre-105 didn't save an OrderList
if (mapping[v->orders.old] == NULL) {
/* This adds the whole shared vehicle chain for case b */
/* Creating an OrderList here is safe because the number of vehicles
* allowed in these savegames matches the number of OrderLists. As
* such each vehicle can get an OrderList and it will (still) fit. */
assert(OrderList::CanAllocateItem());
v->orders.list = mapping[v->orders.old] = new OrderList(v->orders.old, v);
} else {
v->orders.list = mapping[v->orders.old];
@ -752,7 +757,7 @@ void Load_VEHS()
SlObject(v, GetVehicleDescription(vtype));
if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v)) {
if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) {
/* Don't construct the packet with station here, because that'll fail with old savegames */
CargoPacket *cp = new CargoPacket(_cargo_count, _cargo_days, _cargo_source, _cargo_source_xy, _cargo_loaded_at_xy, _cargo_feeder_share);
v->cargo.Append(cp);