Fix a bunch of undefined behaviour detected by the static analyzer in the saved game format.
This commit is contained in:
@@ -78,7 +78,7 @@ public:
|
||||
template<typename T>
|
||||
typename std::enable_if<!detail::is_container<T>::value, size_t>::type
|
||||
extract(size_t i, T& to) const {
|
||||
if(i >= values.size()) return 1;
|
||||
if(i >= values.size()) return 0;
|
||||
// This bizarre construct simply allows us to not include <sstream> here
|
||||
using stream = typename std::conditional<std::is_same<T, T>::value, std::istringstream, void>::type;
|
||||
stream file(values[i]);
|
||||
@@ -229,14 +229,15 @@ public:
|
||||
if(tag == nullptr) return *this;
|
||||
size_t j = i;
|
||||
j += tag->extract(i, value);
|
||||
if(i == j) return cTagFile_TagExtractProxy();
|
||||
return cTagFile_TagExtractProxy(*tag, j);
|
||||
}
|
||||
template<typename T>
|
||||
cTagFile_TagExtractProxy operator>>(T&& value) {
|
||||
cTagFile_TagExtractProxy operator>>(const T& value) {
|
||||
if(tag == nullptr) return *this;
|
||||
size_t j = i;
|
||||
T check = value;
|
||||
j += tag->extract(i, value);
|
||||
j += tag->extract(i, check);
|
||||
if(check != value) {
|
||||
return cTagFile_TagExtractProxy();
|
||||
}
|
||||
@@ -284,7 +285,7 @@ public:
|
||||
cTagFile_TagExtractProxy operator>>(T&& value) const {
|
||||
if(i >= tags.size()) {
|
||||
i = 0;
|
||||
return cTagFile_TagExtractProxy() >> value;
|
||||
return cTagFile_TagExtractProxy() >> std::forward<T>(value);
|
||||
} else {
|
||||
return cTagFile_TagExtractProxy(tags[i++]) >> std::forward<T>(value);
|
||||
}
|
||||
@@ -315,11 +316,12 @@ public:
|
||||
for(size_t n = 0; n < tags.size(); n++) {
|
||||
size_t i = 0;
|
||||
T value;
|
||||
*this >> i >> value;
|
||||
if(*this >> i >> value) {
|
||||
if(i >= values.size()) values.resize(i + 1, def);
|
||||
values[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename Container>
|
||||
typename std::enable_if<!detail::is_pair<typename Container::value_type>::value>::type
|
||||
encodeSparse(const Container& values, typename Container::value_type def = typename Container::value_type()) {
|
||||
@@ -387,13 +389,14 @@ public:
|
||||
for(size_t n = 0; n < tags.size(); n++) {
|
||||
size_t x = 0, y = 0;
|
||||
T value;
|
||||
*this >> x >> y >> value;
|
||||
if(*this >> x >> y >> value) {
|
||||
if(x >= values.width() || y >= values.height()) {
|
||||
values.resize(std::max(x + 1, values.width()), std::max(y + 1, values.height()), def);
|
||||
}
|
||||
values[x][y] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
void encodeSparse(const vector2d<T>& values, T def = T()) {
|
||||
for(size_t x = 0; x < values.width(); x++) {
|
||||
|
@@ -874,7 +874,7 @@ void cMonster::readFrom(const cTagFile_Page& page) {
|
||||
guard = page.contains("GUARD");
|
||||
amorphous = page.contains("AMORPHOUS");
|
||||
for(int i = 0; i < page["ATTACK"].size(); i++) {
|
||||
size_t which_atk;
|
||||
size_t which_atk = 0;
|
||||
auto tmp = page["ATTACK"] >> which_atk;
|
||||
if(which_atk > 0 && which_atk <= a.size()) {
|
||||
which_atk--;
|
||||
@@ -884,7 +884,7 @@ void cMonster::readFrom(const cTagFile_Page& page) {
|
||||
}
|
||||
|
||||
eMonstAbil uAbility::readFrom(const cTagFile_Page& page) {
|
||||
eMonstAbil key;
|
||||
eMonstAbil key = eMonstAbil::NO_ABIL;
|
||||
page["ABIL"] >> key;
|
||||
eMonstAbilCat cat = getMonstAbilCategory(key);
|
||||
switch(cat) {
|
||||
|
@@ -906,7 +906,7 @@ void cParty::readFrom(const cTagFile& file) {
|
||||
|
||||
wipe_sdfs();
|
||||
for(size_t i = 0; i < page["SDF"].size(); i++) {
|
||||
size_t x, y, val;
|
||||
size_t x = sdx_max, y = sdy_max, val = 0;
|
||||
page["SDF"] >> x >> y >> val;
|
||||
if(x <= sdx_max && y <= sdy_max) {
|
||||
stuff_done[x][y] = val;
|
||||
@@ -916,11 +916,11 @@ void cParty::readFrom(const cTagFile& file) {
|
||||
pointers.clear();
|
||||
magic_ptrs.fill(0);
|
||||
for(size_t n = 0; n < page["POINTER"].size(); n++) {
|
||||
int i, j, k;
|
||||
int i = 0, j = 0, k = 0;
|
||||
auto tmp = page["POINTER"] >> i >> j;
|
||||
if(i >= 10 && i < 100) {
|
||||
magic_ptrs[i - 10] = j;
|
||||
} else {
|
||||
} else if(i >= 100 && i < 200) {
|
||||
tmp >> k;
|
||||
pointers[i] = std::make_pair(j, k);
|
||||
}
|
||||
@@ -949,7 +949,7 @@ void cParty::readFrom(const cTagFile& file) {
|
||||
for(size_t n = 0; n < page["TOWNSAVE"].size(); n++) {
|
||||
size_t i;
|
||||
auto tmp = page["TOWNSAVE"] >> i;
|
||||
if(i >= creature_save.size()) continue;
|
||||
if(!tmp || i >= creature_save.size()) continue;
|
||||
std::string hostile;
|
||||
tmp >> creature_save[i].which_town >> hostile;
|
||||
creature_save[i].hostile = hostile == "HOSTILE";
|
||||
@@ -987,25 +987,29 @@ void cParty::readFrom(const cTagFile& file) {
|
||||
}
|
||||
} else if(page.getFirstKey() == "BOAT") {
|
||||
size_t i;
|
||||
page["BOAT"] >> i;
|
||||
if(page["BOAT"] >> i) {
|
||||
if(i >= boats.size()) boats.resize(i + 1);
|
||||
boats[i].exists = true;
|
||||
boats[i].readFrom(page);
|
||||
}
|
||||
} else if(page.getFirstKey() == "HORSE") {
|
||||
size_t i;
|
||||
page["HORSE"] >> i;
|
||||
if(page["HORSE"] >> i) {
|
||||
if(i >= horses.size()) horses.resize(i + 1);
|
||||
horses[i].exists = true;
|
||||
horses[i].readFrom(page);
|
||||
}
|
||||
} else if(page.getFirstKey() == "MAGICSTORE") {
|
||||
size_t i, j;
|
||||
page["MAGICSTORE"] >> i >> j;
|
||||
if(page["MAGICSTORE"] >> i >> j) {
|
||||
magic_store_items[i][j].readFrom(page);
|
||||
}
|
||||
} else if(page.getFirstKey() == "ENCOUNTER") {
|
||||
int i;
|
||||
page["ENCOUNTER"] >> i;
|
||||
if(page["ENCOUNTER"] >> i) {
|
||||
out_c[i].exists = true;
|
||||
out_c[i].readFrom(page);
|
||||
}
|
||||
} else if(page.getFirstKey() == "TIMER") {
|
||||
size_t i, j;
|
||||
cTimer timer;
|
||||
@@ -1016,18 +1020,20 @@ void cParty::readFrom(const cTagFile& file) {
|
||||
}
|
||||
} else if(page.getFirstKey() == "CREATURE") {
|
||||
size_t i, j;
|
||||
page["CREATURE"] >> i >> j;
|
||||
if(page["CREATURE"] >> i >> j) {
|
||||
if(i < 0 || i >= creature_save.size()) continue;
|
||||
creature_save[i].init(j);
|
||||
creature_save[i][j].readFrom(page);
|
||||
}
|
||||
} else if(page.getFirstKey() == "STORED") {
|
||||
size_t i, j;
|
||||
page["STORED"] >> i >> j;
|
||||
if(page["STORED"] >> i >> j) {
|
||||
if(i >= 3) continue;
|
||||
if(j >= stored_items[i].size()) {
|
||||
stored_items[i].resize(j + 1);
|
||||
}
|
||||
stored_items[i][j].readFrom(page);
|
||||
}
|
||||
} else if(page.getFirstKey() == "SUMMON") {
|
||||
page["SUMMON"] >> monst_i;
|
||||
if(monst_i >= summons.size()) {
|
||||
@@ -1062,7 +1068,7 @@ void cParty::readFrom(const cTagFile& file) {
|
||||
} else if(page.getFirstKey() == "JOBBANK") {
|
||||
size_t i;
|
||||
job_bank_t bank;
|
||||
page["JOBBANK"] >> i >> bank.anger;
|
||||
if(page["JOBBANK"] >> i >> bank.anger) {
|
||||
if(i >= job_banks.size()) {
|
||||
job_banks.resize(i + 1);
|
||||
}
|
||||
@@ -1074,6 +1080,7 @@ void cParty::readFrom(const cTagFile& file) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cPlayer& cParty::operator[](unsigned short n){
|
||||
if(n > 6) throw std::out_of_range("Attempt to access a player that doesn't exist.");
|
||||
|
@@ -1300,23 +1300,23 @@ void cPlayer::readFrom(const cTagFile& file) {
|
||||
|
||||
equip.reset();
|
||||
for(size_t n = 0; n < page["EQUIP"].size(); n++) {
|
||||
size_t i;
|
||||
size_t i = equip.size();
|
||||
page["EQUIP"] >> i;
|
||||
equip[i] = true;
|
||||
if(i < equip.size()) equip[i] = true;
|
||||
}
|
||||
|
||||
mage_spells.reset();
|
||||
for(size_t n = 0; n < page["MAGE"].size(); n++) {
|
||||
size_t i;
|
||||
size_t i = mage_spells.size();
|
||||
page["MAGE"] >> i;
|
||||
mage_spells[i] = true;
|
||||
if(i < mage_spells.size()) mage_spells[i] = true;
|
||||
}
|
||||
|
||||
priest_spells.reset();
|
||||
for(size_t n = 0; n < page["PRIEST"].size(); n++) {
|
||||
size_t i;
|
||||
size_t i = priest_spells.size();
|
||||
page["PRIEST"] >> i;
|
||||
priest_spells[i] = true;
|
||||
if(i < priest_spells.size()) priest_spells[i] = true;
|
||||
}
|
||||
|
||||
traits.clear();
|
||||
@@ -1336,7 +1336,7 @@ void cPlayer::readFrom(const cTagFile& file) {
|
||||
party->next_pc_id = max(unique_id + 1, party->next_pc_id);
|
||||
}
|
||||
} else if(page.getFirstKey() == "ITEM") {
|
||||
size_t i;
|
||||
size_t i = items.size();
|
||||
page["ITEM"] >> i;
|
||||
if(i >= items.size()) continue;
|
||||
items[i].readFrom(page);
|
||||
|
@@ -910,18 +910,20 @@ void cCurTown::readFrom(const cTagFile& file){
|
||||
}
|
||||
} else if(page.getFirstKey() == "ITEM") {
|
||||
size_t i;
|
||||
page["ITEM"] >> i;
|
||||
if(page["ITEM"] >> i) {
|
||||
if(i >= items.size()) items.resize(i + 1);
|
||||
items[i].readFrom(page);
|
||||
}
|
||||
} else if(page.getFirstKey() == "CREATURE") {
|
||||
size_t i;
|
||||
page["CREATURE"] >> i;
|
||||
if(page["CREATURE"] >> i) {
|
||||
monst.init(i);
|
||||
monst[i].readFrom(page);
|
||||
monst[i].active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cCurTown::cCurTown(cUniverse& univ) : univ(univ) {
|
||||
arena = nullptr;
|
||||
|
Reference in New Issue
Block a user