summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsmatz <smatz@openttd.org>2011-02-08 18:34:13 +0000
committersmatz <smatz@openttd.org>2011-02-08 18:34:13 +0000
commit887a7724dc3f68cdd3d0c566c66adf00696e4bc0 (patch)
tree00a9055a6bc84b0f9d278e3a8faac022dd0a3778
parent364ef8e6e6342f8f777da561571422c8c57c402b (diff)
downloadopenttd-887a7724dc3f68cdd3d0c566c66adf00696e4bc0.tar.xz
(svn r22025) -Fix: verify there is enough space in the pool when creating new pool items while loading old savegames
-rw-r--r--src/engine.cpp6
-rw-r--r--src/saveload/afterload.cpp19
-rw-r--r--src/saveload/saveload.cpp2
-rw-r--r--src/saveload/saveload.h2
-rw-r--r--src/saveload/station_sl.cpp6
-rw-r--r--src/saveload/vehicle_sl.cpp7
6 files changed, 38 insertions, 4 deletions
diff --git a/src/engine.cpp b/src/engine.cpp
index d08fbef32..8774b0b3e 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -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);
}
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
index f73ef2189..17ac9bc81 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -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);
}
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index ce3281715..ae759f4d1 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -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) {
diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h
index f9d191467..ff18615c2 100644
--- a/src/saveload/saveload.h
+++ b/src/saveload/saveload.h
@@ -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();
diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp
index b0535d9d2..330425024 100644
--- a/src/saveload/station_sl.cpp
+++ b/src/saveload/station_sl.cpp
@@ -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);
}
diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp
index d1558d966..f264c3d10 100644
--- a/src/saveload/vehicle_sl.cpp
+++ b/src/saveload/vehicle_sl.cpp
@@ -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);