summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryexo <yexo@openttd.org>2011-03-03 20:26:19 +0000
committeryexo <yexo@openttd.org>2011-03-03 20:26:19 +0000
commitb74de9ff7223b4402abdc1e0e8aad68a5187009e (patch)
treee886b4a1efff822443840a384a86b8886e3f99ea
parent18a2fadf35f1555085551adf7c6d9defd765ce20 (diff)
downloadopenttd-b74de9ff7223b4402abdc1e0e8aad68a5187009e.tar.xz
(svn r22165) -Fix: [NewGRF] memory leak if an industry newgrf had more than one prop A or 15
-rw-r--r--src/newgrf.cpp44
1 files changed, 28 insertions, 16 deletions
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index cd1192443..a60e76789 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2524,6 +2524,20 @@ static bool ValidateIndustryLayout(const IndustryTileTable *layout, int size)
return true;
}
+/** Clean the tile table of the IndustrySpec if it's needed. */
+static void CleanIndustryTileTable(IndustrySpec *ind)
+{
+ if (HasBit(ind->cleanup_flag, CLEAN_TILELAYOUT) && ind->table != NULL) {
+ for (int j = 0; j < ind->num_table; j++) {
+ /* remove the individual layouts */
+ free((void*)ind->table[j]);
+ }
+ /* remove the layouts pointers */
+ free((void*)ind->table);
+ ind->table = NULL;
+ }
+}
+
static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, ByteReader *buf)
{
ChangeInfoResult ret = CIR_SUCCESS;
@@ -2598,20 +2612,20 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
}
case 0x0A: { // Set industry layout(s)
- indsp->num_table = buf->ReadByte(); // Number of layaouts
+ byte new_num_layouts = buf->ReadByte(); // Number of layaouts
/* We read the total size in bytes, but we can't rely on the
* newgrf to provide a sane value. First assume the value is
* sane but later on we make sure we enlarge the array if the
* newgrf contains more data. Each tile uses either 3 or 5
* bytes, so to play it safe we assume 3. */
uint32 def_num_tiles = buf->ReadDWord() / 3 + 1;
- IndustryTileTable **tile_table = CallocT<IndustryTileTable*>(indsp->num_table); // Table with tiles to compose an industry
+ IndustryTileTable **tile_table = CallocT<IndustryTileTable*>(new_num_layouts); // Table with tiles to compose an industry
IndustryTileTable *itt = CallocT<IndustryTileTable>(def_num_tiles); // Temporary array to read the tile layouts from the GRF
uint size;
const IndustryTileTable *copy_from;
try {
- for (byte j = 0; j < indsp->num_table; j++) {
+ for (byte j = 0; j < new_num_layouts; j++) {
for (uint k = 0;; k++) {
if (k >= def_num_tiles) {
grfmsg(3, "IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry %u.", indid);
@@ -2674,7 +2688,7 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
if (!ValidateIndustryLayout(copy_from, size)) {
/* The industry layout was not valid, so skip this one. */
grfmsg(1, "IndustriesChangeInfo: Invalid industry layout for industry id %u. Ignoring", indid);
- indsp->num_table--;
+ new_num_layouts--;
j--;
} else {
tile_table[j] = CallocT<IndustryTileTable>(size);
@@ -2682,7 +2696,7 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
}
}
} catch (...) {
- for (int i = 0; i < indsp->num_table; i++) {
+ for (int i = 0; i < new_num_layouts; i++) {
free(tile_table[i]);
}
free(tile_table);
@@ -2690,9 +2704,12 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
throw;
}
+ /* Clean the tile table if it was already set by a previous prop A. */
+ CleanIndustryTileTable(indsp);
/* Install final layout construction in the industry spec */
+ indsp->num_table = new_num_layouts;
indsp->table = tile_table;
- SetBit(indsp->cleanup_flag, 1);
+ SetBit(indsp->cleanup_flag, CLEAN_TILELAYOUT);
free(itt);
break;
}
@@ -2755,8 +2772,11 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
throw;
}
+ if (HasBit(indsp->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
+ free((void*)indsp->random_sounds);
+ }
indsp->random_sounds = sounds;
- SetBit(indsp->cleanup_flag, 0);
+ SetBit(indsp->cleanup_flag, CLEAN_RANDOMSOUNDS);
break;
}
@@ -7130,15 +7150,7 @@ static void ResetCustomIndustries()
}
/* We need to remove the tiles layouts */
- if (HasBit(ind->cleanup_flag, CLEAN_TILELAYOUT) && ind->table != NULL) {
- for (int j = 0; j < ind->num_table; j++) {
- /* remove the individual layouts */
- free((void*)ind->table[j]);
- }
- /* remove the layouts pointers */
- free((void*)ind->table);
- ind->table = NULL;
- }
+ CleanIndustryTileTable(ind);
free(ind);
}