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>
|
template<typename T>
|
||||||
typename std::enable_if<!detail::is_container<T>::value, size_t>::type
|
typename std::enable_if<!detail::is_container<T>::value, size_t>::type
|
||||||
extract(size_t i, T& to) const {
|
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
|
// 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;
|
using stream = typename std::conditional<std::is_same<T, T>::value, std::istringstream, void>::type;
|
||||||
stream file(values[i]);
|
stream file(values[i]);
|
||||||
@@ -229,14 +229,15 @@ public:
|
|||||||
if(tag == nullptr) return *this;
|
if(tag == nullptr) return *this;
|
||||||
size_t j = i;
|
size_t j = i;
|
||||||
j += tag->extract(i, value);
|
j += tag->extract(i, value);
|
||||||
|
if(i == j) return cTagFile_TagExtractProxy();
|
||||||
return cTagFile_TagExtractProxy(*tag, j);
|
return cTagFile_TagExtractProxy(*tag, j);
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
cTagFile_TagExtractProxy operator>>(T&& value) {
|
cTagFile_TagExtractProxy operator>>(const T& value) {
|
||||||
if(tag == nullptr) return *this;
|
if(tag == nullptr) return *this;
|
||||||
size_t j = i;
|
size_t j = i;
|
||||||
T check = value;
|
T check = value;
|
||||||
j += tag->extract(i, value);
|
j += tag->extract(i, check);
|
||||||
if(check != value) {
|
if(check != value) {
|
||||||
return cTagFile_TagExtractProxy();
|
return cTagFile_TagExtractProxy();
|
||||||
}
|
}
|
||||||
@@ -284,7 +285,7 @@ public:
|
|||||||
cTagFile_TagExtractProxy operator>>(T&& value) const {
|
cTagFile_TagExtractProxy operator>>(T&& value) const {
|
||||||
if(i >= tags.size()) {
|
if(i >= tags.size()) {
|
||||||
i = 0;
|
i = 0;
|
||||||
return cTagFile_TagExtractProxy() >> value;
|
return cTagFile_TagExtractProxy() >> std::forward<T>(value);
|
||||||
} else {
|
} else {
|
||||||
return cTagFile_TagExtractProxy(tags[i++]) >> std::forward<T>(value);
|
return cTagFile_TagExtractProxy(tags[i++]) >> std::forward<T>(value);
|
||||||
}
|
}
|
||||||
@@ -315,9 +316,10 @@ public:
|
|||||||
for(size_t n = 0; n < tags.size(); n++) {
|
for(size_t n = 0; n < tags.size(); n++) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
T value;
|
T value;
|
||||||
*this >> i >> value;
|
if(*this >> i >> value) {
|
||||||
if(i >= values.size()) values.resize(i + 1, def);
|
if(i >= values.size()) values.resize(i + 1, def);
|
||||||
values[i] = value;
|
values[i] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
@@ -387,11 +389,12 @@ public:
|
|||||||
for(size_t n = 0; n < tags.size(); n++) {
|
for(size_t n = 0; n < tags.size(); n++) {
|
||||||
size_t x = 0, y = 0;
|
size_t x = 0, y = 0;
|
||||||
T value;
|
T value;
|
||||||
*this >> x >> y >> value;
|
if(*this >> x >> y >> value) {
|
||||||
if(x >= values.width() || y >= values.height()) {
|
if(x >= values.width() || y >= values.height()) {
|
||||||
values.resize(std::max(x + 1, values.width()), std::max(y + 1, values.height()), def);
|
values.resize(std::max(x + 1, values.width()), std::max(y + 1, values.height()), def);
|
||||||
|
}
|
||||||
|
values[x][y] = value;
|
||||||
}
|
}
|
||||||
values[x][y] = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@@ -874,7 +874,7 @@ void cMonster::readFrom(const cTagFile_Page& page) {
|
|||||||
guard = page.contains("GUARD");
|
guard = page.contains("GUARD");
|
||||||
amorphous = page.contains("AMORPHOUS");
|
amorphous = page.contains("AMORPHOUS");
|
||||||
for(int i = 0; i < page["ATTACK"].size(); i++) {
|
for(int i = 0; i < page["ATTACK"].size(); i++) {
|
||||||
size_t which_atk;
|
size_t which_atk = 0;
|
||||||
auto tmp = page["ATTACK"] >> which_atk;
|
auto tmp = page["ATTACK"] >> which_atk;
|
||||||
if(which_atk > 0 && which_atk <= a.size()) {
|
if(which_atk > 0 && which_atk <= a.size()) {
|
||||||
which_atk--;
|
which_atk--;
|
||||||
@@ -884,7 +884,7 @@ void cMonster::readFrom(const cTagFile_Page& page) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eMonstAbil uAbility::readFrom(const cTagFile_Page& page) {
|
eMonstAbil uAbility::readFrom(const cTagFile_Page& page) {
|
||||||
eMonstAbil key;
|
eMonstAbil key = eMonstAbil::NO_ABIL;
|
||||||
page["ABIL"] >> key;
|
page["ABIL"] >> key;
|
||||||
eMonstAbilCat cat = getMonstAbilCategory(key);
|
eMonstAbilCat cat = getMonstAbilCategory(key);
|
||||||
switch(cat) {
|
switch(cat) {
|
||||||
|
@@ -906,7 +906,7 @@ void cParty::readFrom(const cTagFile& file) {
|
|||||||
|
|
||||||
wipe_sdfs();
|
wipe_sdfs();
|
||||||
for(size_t i = 0; i < page["SDF"].size(); i++) {
|
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;
|
page["SDF"] >> x >> y >> val;
|
||||||
if(x <= sdx_max && y <= sdy_max) {
|
if(x <= sdx_max && y <= sdy_max) {
|
||||||
stuff_done[x][y] = val;
|
stuff_done[x][y] = val;
|
||||||
@@ -916,11 +916,11 @@ void cParty::readFrom(const cTagFile& file) {
|
|||||||
pointers.clear();
|
pointers.clear();
|
||||||
magic_ptrs.fill(0);
|
magic_ptrs.fill(0);
|
||||||
for(size_t n = 0; n < page["POINTER"].size(); n++) {
|
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;
|
auto tmp = page["POINTER"] >> i >> j;
|
||||||
if(i >= 10 && i < 100) {
|
if(i >= 10 && i < 100) {
|
||||||
magic_ptrs[i - 10] = j;
|
magic_ptrs[i - 10] = j;
|
||||||
} else {
|
} else if(i >= 100 && i < 200) {
|
||||||
tmp >> k;
|
tmp >> k;
|
||||||
pointers[i] = std::make_pair(j, 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++) {
|
for(size_t n = 0; n < page["TOWNSAVE"].size(); n++) {
|
||||||
size_t i;
|
size_t i;
|
||||||
auto tmp = page["TOWNSAVE"] >> i;
|
auto tmp = page["TOWNSAVE"] >> i;
|
||||||
if(i >= creature_save.size()) continue;
|
if(!tmp || i >= creature_save.size()) continue;
|
||||||
std::string hostile;
|
std::string hostile;
|
||||||
tmp >> creature_save[i].which_town >> hostile;
|
tmp >> creature_save[i].which_town >> hostile;
|
||||||
creature_save[i].hostile = hostile == "HOSTILE";
|
creature_save[i].hostile = hostile == "HOSTILE";
|
||||||
@@ -987,25 +987,29 @@ void cParty::readFrom(const cTagFile& file) {
|
|||||||
}
|
}
|
||||||
} else if(page.getFirstKey() == "BOAT") {
|
} else if(page.getFirstKey() == "BOAT") {
|
||||||
size_t i;
|
size_t i;
|
||||||
page["BOAT"] >> i;
|
if(page["BOAT"] >> i) {
|
||||||
if(i >= boats.size()) boats.resize(i + 1);
|
if(i >= boats.size()) boats.resize(i + 1);
|
||||||
boats[i].exists = true;
|
boats[i].exists = true;
|
||||||
boats[i].readFrom(page);
|
boats[i].readFrom(page);
|
||||||
|
}
|
||||||
} else if(page.getFirstKey() == "HORSE") {
|
} else if(page.getFirstKey() == "HORSE") {
|
||||||
size_t i;
|
size_t i;
|
||||||
page["HORSE"] >> i;
|
if(page["HORSE"] >> i) {
|
||||||
if(i >= horses.size()) horses.resize(i + 1);
|
if(i >= horses.size()) horses.resize(i + 1);
|
||||||
horses[i].exists = true;
|
horses[i].exists = true;
|
||||||
horses[i].readFrom(page);
|
horses[i].readFrom(page);
|
||||||
|
}
|
||||||
} else if(page.getFirstKey() == "MAGICSTORE") {
|
} else if(page.getFirstKey() == "MAGICSTORE") {
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
page["MAGICSTORE"] >> i >> j;
|
if(page["MAGICSTORE"] >> i >> j) {
|
||||||
magic_store_items[i][j].readFrom(page);
|
magic_store_items[i][j].readFrom(page);
|
||||||
|
}
|
||||||
} else if(page.getFirstKey() == "ENCOUNTER") {
|
} else if(page.getFirstKey() == "ENCOUNTER") {
|
||||||
int i;
|
int i;
|
||||||
page["ENCOUNTER"] >> i;
|
if(page["ENCOUNTER"] >> i) {
|
||||||
out_c[i].exists = true;
|
out_c[i].exists = true;
|
||||||
out_c[i].readFrom(page);
|
out_c[i].readFrom(page);
|
||||||
|
}
|
||||||
} else if(page.getFirstKey() == "TIMER") {
|
} else if(page.getFirstKey() == "TIMER") {
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
cTimer timer;
|
cTimer timer;
|
||||||
@@ -1016,18 +1020,20 @@ void cParty::readFrom(const cTagFile& file) {
|
|||||||
}
|
}
|
||||||
} else if(page.getFirstKey() == "CREATURE") {
|
} else if(page.getFirstKey() == "CREATURE") {
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
page["CREATURE"] >> i >> j;
|
if(page["CREATURE"] >> i >> j) {
|
||||||
if(i < 0 || i >= creature_save.size()) continue;
|
if(i < 0 || i >= creature_save.size()) continue;
|
||||||
creature_save[i].init(j);
|
creature_save[i].init(j);
|
||||||
creature_save[i][j].readFrom(page);
|
creature_save[i][j].readFrom(page);
|
||||||
|
}
|
||||||
} else if(page.getFirstKey() == "STORED") {
|
} else if(page.getFirstKey() == "STORED") {
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
page["STORED"] >> i >> j;
|
if(page["STORED"] >> i >> j) {
|
||||||
if(i >= 3) continue;
|
if(i >= 3) continue;
|
||||||
if(j >= stored_items[i].size()) {
|
if(j >= stored_items[i].size()) {
|
||||||
stored_items[i].resize(j + 1);
|
stored_items[i].resize(j + 1);
|
||||||
|
}
|
||||||
|
stored_items[i][j].readFrom(page);
|
||||||
}
|
}
|
||||||
stored_items[i][j].readFrom(page);
|
|
||||||
} else if(page.getFirstKey() == "SUMMON") {
|
} else if(page.getFirstKey() == "SUMMON") {
|
||||||
page["SUMMON"] >> monst_i;
|
page["SUMMON"] >> monst_i;
|
||||||
if(monst_i >= summons.size()) {
|
if(monst_i >= summons.size()) {
|
||||||
@@ -1062,15 +1068,16 @@ void cParty::readFrom(const cTagFile& file) {
|
|||||||
} else if(page.getFirstKey() == "JOBBANK") {
|
} else if(page.getFirstKey() == "JOBBANK") {
|
||||||
size_t i;
|
size_t i;
|
||||||
job_bank_t bank;
|
job_bank_t bank;
|
||||||
page["JOBBANK"] >> i >> bank.anger;
|
if(page["JOBBANK"] >> i >> bank.anger) {
|
||||||
if(i >= job_banks.size()) {
|
if(i >= job_banks.size()) {
|
||||||
job_banks.resize(i + 1);
|
job_banks.resize(i + 1);
|
||||||
|
}
|
||||||
|
std::vector<int> jobs;
|
||||||
|
page["JOB"].extractSparse(jobs);
|
||||||
|
bank.inited = !jobs.empty();
|
||||||
|
std::copy_n(jobs.begin(), std::min(jobs.size(), bank.jobs.size()), bank.jobs.begin());
|
||||||
|
job_banks[i] = bank;
|
||||||
}
|
}
|
||||||
std::vector<int> jobs;
|
|
||||||
page["JOB"].extractSparse(jobs);
|
|
||||||
bank.inited = !jobs.empty();
|
|
||||||
std::copy_n(jobs.begin(), std::min(jobs.size(), bank.jobs.size()), bank.jobs.begin());
|
|
||||||
job_banks[i] = bank;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1300,23 +1300,23 @@ void cPlayer::readFrom(const cTagFile& file) {
|
|||||||
|
|
||||||
equip.reset();
|
equip.reset();
|
||||||
for(size_t n = 0; n < page["EQUIP"].size(); n++) {
|
for(size_t n = 0; n < page["EQUIP"].size(); n++) {
|
||||||
size_t i;
|
size_t i = equip.size();
|
||||||
page["EQUIP"] >> i;
|
page["EQUIP"] >> i;
|
||||||
equip[i] = true;
|
if(i < equip.size()) equip[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mage_spells.reset();
|
mage_spells.reset();
|
||||||
for(size_t n = 0; n < page["MAGE"].size(); n++) {
|
for(size_t n = 0; n < page["MAGE"].size(); n++) {
|
||||||
size_t i;
|
size_t i = mage_spells.size();
|
||||||
page["MAGE"] >> i;
|
page["MAGE"] >> i;
|
||||||
mage_spells[i] = true;
|
if(i < mage_spells.size()) mage_spells[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
priest_spells.reset();
|
priest_spells.reset();
|
||||||
for(size_t n = 0; n < page["PRIEST"].size(); n++) {
|
for(size_t n = 0; n < page["PRIEST"].size(); n++) {
|
||||||
size_t i;
|
size_t i = priest_spells.size();
|
||||||
page["PRIEST"] >> i;
|
page["PRIEST"] >> i;
|
||||||
priest_spells[i] = true;
|
if(i < priest_spells.size()) priest_spells[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
traits.clear();
|
traits.clear();
|
||||||
@@ -1336,7 +1336,7 @@ void cPlayer::readFrom(const cTagFile& file) {
|
|||||||
party->next_pc_id = max(unique_id + 1, party->next_pc_id);
|
party->next_pc_id = max(unique_id + 1, party->next_pc_id);
|
||||||
}
|
}
|
||||||
} else if(page.getFirstKey() == "ITEM") {
|
} else if(page.getFirstKey() == "ITEM") {
|
||||||
size_t i;
|
size_t i = items.size();
|
||||||
page["ITEM"] >> i;
|
page["ITEM"] >> i;
|
||||||
if(i >= items.size()) continue;
|
if(i >= items.size()) continue;
|
||||||
items[i].readFrom(page);
|
items[i].readFrom(page);
|
||||||
|
@@ -910,15 +910,17 @@ void cCurTown::readFrom(const cTagFile& file){
|
|||||||
}
|
}
|
||||||
} else if(page.getFirstKey() == "ITEM") {
|
} else if(page.getFirstKey() == "ITEM") {
|
||||||
size_t i;
|
size_t i;
|
||||||
page["ITEM"] >> i;
|
if(page["ITEM"] >> i) {
|
||||||
if(i >= items.size()) items.resize(i + 1);
|
if(i >= items.size()) items.resize(i + 1);
|
||||||
items[i].readFrom(page);
|
items[i].readFrom(page);
|
||||||
|
}
|
||||||
} else if(page.getFirstKey() == "CREATURE") {
|
} else if(page.getFirstKey() == "CREATURE") {
|
||||||
size_t i;
|
size_t i;
|
||||||
page["CREATURE"] >> i;
|
if(page["CREATURE"] >> i) {
|
||||||
monst.init(i);
|
monst.init(i);
|
||||||
monst[i].readFrom(page);
|
monst[i].readFrom(page);
|
||||||
monst[i].active = true;
|
monst[i].active = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user