vector2d: try to protect the access against bad index, to be improved...

+ details rewriting
This commit is contained in:
ALONSO Laurent
2021-10-24 13:14:41 +02:00
committed by Celtic Minstrel
parent 282c640173
commit f3a96391b5
8 changed files with 133 additions and 60 deletions

View File

@@ -727,8 +727,8 @@ location find_clear_spot(location from_where,short mode) {
if(!loc_off_act_area(loc) && !is_blocked(loc) if(!loc_off_act_area(loc) && !is_blocked(loc)
&& can_see_light(from_where,loc,combat_obscurity) == 0 && can_see_light(from_where,loc,combat_obscurity) == 0
&& (!is_combat() || univ.target_there(loc,TARG_PC) == nullptr) && (!is_combat() || univ.target_there(loc,TARG_PC) == nullptr)
&& (!(is_town()) || (loc != univ.party.town_loc)) && (!is_town() || loc != univ.party.town_loc)
&& (!(univ.town.fields[loc.x][loc.y] & blocking_fields))) { && (!is_town() || !(univ.town.fields[loc.x][loc.y] & blocking_fields))) {
if((mode == 0) || ((mode == 1) && (adjacent(from_where,loc)))) if((mode == 0) || ((mode == 1) && (adjacent(from_where,loc))))
return loc; return loc;
else store_loc = loc; else store_loc = loc;

View File

@@ -196,19 +196,19 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
if(mode == eSpecCtx::OUT_MOVE) { if(mode == eSpecCtx::OUT_MOVE) {
out_where = global_to_local(where_check); out_where = global_to_local(where_check);
for(short i = 0; i < univ.out->special_locs.size(); i++) for(short i = 0; i < univ.out->special_locs.size(); i++) {
if(out_where == univ.out->special_locs[i]) { if(out_where != univ.out->special_locs[i]) continue;
spec_num = univ.out->special_locs[i].spec; spec_num = univ.out->special_locs[i].spec;
// call special // call special
run_special(mode, eSpecCtxType::OUTDOOR, spec_num, out_where, &s1, &s2); run_special(mode, eSpecCtxType::OUTDOOR, spec_num, out_where, &s1, &s2);
if(s1 > 0) if(s1 > 0)
can_enter = false; can_enter = false;
else if(s2 > 0) else if(s2 > 0)
*forced = true; *forced = true;
erase_out_specials(); erase_out_specials();
put_pc_screen(); put_pc_screen();
put_item_screen(stat_window); put_item_screen(stat_window);
} }
} }
if (is_combat()) { if (is_combat()) {
@@ -240,26 +240,26 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
} }
if((mode == eSpecCtx::TOWN_MOVE || (mode == eSpecCtx::COMBAT_MOVE && which_combat_type == 1)) if((mode == eSpecCtx::TOWN_MOVE || (mode == eSpecCtx::COMBAT_MOVE && which_combat_type == 1))
&& can_enter && univ.town.is_special(where_check.x,where_check.y)) { && can_enter && univ.town.is_special(where_check.x,where_check.y)) {
for(short i = 0; i < univ.town->special_locs.size(); i++) for(short i = 0; i < univ.town->special_locs.size(); i++) {
if(where_check == univ.town->special_locs[i]) { if(where_check != univ.town->special_locs[i]) continue;
spec_num = univ.town->special_locs[i].spec; spec_num = univ.town->special_locs[i].spec;
bool runSpecial = false; bool runSpecial = false;
if(!is_blocked(where_check)) runSpecial = true; if(!is_blocked(where_check)) runSpecial = true;
if(ter_special == eTerSpec::CHANGE_WHEN_STEP_ON) runSpecial = true; if(ter_special == eTerSpec::CHANGE_WHEN_STEP_ON) runSpecial = true;
if(ter_special == eTerSpec::CALL_SPECIAL) runSpecial = true; if(ter_special == eTerSpec::CALL_SPECIAL) runSpecial = true;
if(univ.town->specials[spec_num].type == eSpecType::CANT_ENTER) if(univ.town->specials[spec_num].type == eSpecType::CANT_ENTER)
runSpecial = true; runSpecial = true;
if(!univ.scenario.is_legacy && univ.party.in_boat >= 0 && terrain.boat_over) if(!univ.scenario.is_legacy && univ.party.in_boat >= 0 && terrain.boat_over)
runSpecial = true; runSpecial = true;
if(runSpecial) { if(runSpecial) {
give_help(54,0); give_help(54,0);
run_special(mode, eSpecCtxType::TOWN, spec_num, where_check, &s1, &s2); run_special(mode, eSpecCtxType::TOWN, spec_num, where_check, &s1, &s2);
if(s1 > 0) if(s1 > 0)
can_enter = false; can_enter = false;
else if(s2 > 0) else if(s2 > 0)
*forced = true; *forced = true;
}
} }
}
put_pc_screen(); put_pc_screen();
put_item_screen(stat_window); put_item_screen(stat_window);
} }

View File

@@ -837,15 +837,18 @@ void create_out_combat_terrain(short ter_type,short num_walls,bool is_road) {
univ.town.fields[i][j] = 0; univ.town.fields[i][j] = 0;
if((j <= 8) || (j >= 35) || (i <= 8) || (i >= 35)) if((j <= 8) || (j >= 35) || (i <= 8) || (i >= 35))
univ.town->terrain(i,j) = 90; univ.town->terrain(i,j) = 90;
else univ.town->terrain(i,j) = ter_base[arena]; else
} univ.town->terrain(i,j) = ter_base[arena];
for(short i = 0; i < 48; i++) if (univ.town->terrain(i,j) == 90)
for(short j = 0; j < 48; j++) continue;
for(short k = 0; k < 5; k++) for(short k = 0; k < 5; k++) {
if((univ.town->terrain(i,j) != 90) && (get_ran(1,1,1000) < terrain_odds[arena][k * 2 + 1])) if(get_ran(1,1,1000) < terrain_odds[arena][k * 2 + 1]) {
univ.town->terrain(i,j) = terrain_odds[arena][k * 2]; univ.town->terrain(i,j) = terrain_odds[arena][k * 2];
break;
univ.town->terrain(0,0) = ter_base[arena]; }
}
}
univ.town->terrain(0,0) = ter_base[arena]; // to force an exit position?
bool is_bridge = (arena == 3 || arena == 4); bool is_bridge = (arena == 3 || arena == 4);

View File

@@ -48,6 +48,16 @@ void cScenario::destroy_terrain() {
} }
} }
cOutdoors *cScenario::get_bad_outdoor()
{
static std::shared_ptr<cOutdoors> badOutdoor;
if (!badOutdoor)
badOutdoor=std::make_shared<cOutdoors>(*this);
badOutdoor->reattach(*this);
badOutdoor->name="Bad Outdoor";
return badOutdoor.get();
}
cScenario::cScenario() { cScenario::cScenario() {
std::string temp_str; std::string temp_str;
@@ -68,6 +78,7 @@ cScenario::cScenario() {
bg_fight = 4; bg_fight = 4;
bg_town = 13; bg_town = 13;
bg_dungeon = 9; bg_dungeon = 9;
outdoors.set_get_default_function([this](){return get_bad_outdoor();});
// ASAN used but unset // ASAN used but unset
is_legacy = false; is_legacy = false;
for(short i = 0; i < town_mods.size(); i++) { for(short i = 0; i < town_mods.size(); i++) {
@@ -143,6 +154,7 @@ cScenario::cScenario(const cScenario& other)
for(size_t i = 0; i < outdoors.width(); i++) for(size_t i = 0; i < outdoors.width(); i++)
for(size_t j = 0; j < outdoors.height(); j++) for(size_t j = 0; j < outdoors.height(); j++)
outdoors[i][j] = new cOutdoors(*other.outdoors[i][j]); outdoors[i][j] = new cOutdoors(*other.outdoors[i][j]);
outdoors.set_get_default_function([this](){return get_bad_outdoor();});
} }
cScenario::cScenario(cScenario&& other) { cScenario::cScenario(cScenario&& other) {

View File

@@ -132,6 +132,9 @@ public:
void reset_version(); void reset_version();
explicit cScenario(); explicit cScenario();
~cScenario(); ~cScenario();
cOutdoors *get_bad_outdoor();
// Copy-and-swap // Copy-and-swap
void swap(cScenario& other); void swap(cScenario& other);
cScenario(const cScenario& other); cScenario(const cScenario& other);

View File

@@ -85,7 +85,7 @@ void cTown::import_legacy(T const & old, int){
// Try to fix specials that could be triggered while in a boat // Try to fix specials that could be triggered while in a boat
// (Boats never triggered specials in the old BoE, so we probably don't want them to trigger.) // (Boats never triggered specials in the old BoE, so we probably don't want them to trigger.)
int found_spec = -1; int found_spec = -1;
for(int k = 0; k < 50; k++) { for(int k = 0; k < special_locs.size(); k++) {
if(i == special_locs[k].x && j == special_locs[k].y) { if(i == special_locs[k].x && j == special_locs[k].y) {
found_spec = k; found_spec = k;
break; break;

View File

@@ -26,7 +26,6 @@ void set_string(std::string string,std::string string2);
bool is_special(short i,short j); bool is_special(short i,short j);
void take_special(short i,short j); void take_special(short i,short j);
void make_special(short i,short j); void make_special(short i,short j);
void sort_specials();
bool is_field_type(short i,short j,eFieldType field_type); bool is_field_type(short i,short j,eFieldType field_type);
void make_field_type(short i,short j,eFieldType field_type); void make_field_type(short i,short j,eFieldType field_type);
void take_field_type(short i,short j,eFieldType field_type); void take_field_type(short i,short j,eFieldType field_type);

View File

@@ -12,6 +12,7 @@
// Tried using boost::multi_array, but it kept causing weird issues, so I decided to make my own. // Tried using boost::multi_array, but it kept causing weird issues, so I decided to make my own.
// TODO: Fill out missing members (should have equivalents for most of the stuff in std::vector) // TODO: Fill out missing members (should have equivalents for most of the stuff in std::vector)
#include <functional>
#include <vector> #include <vector>
template<typename Type, typename Alloc = std::allocator<Type>> class vector2d { template<typename Type, typename Alloc = std::allocator<Type>> class vector2d {
@@ -21,6 +22,7 @@ template<typename Type, typename Alloc = std::allocator<Type>> class vector2d {
friend class const_col_ref; friend class const_col_ref;
std::vector<Type, Alloc> data; std::vector<Type, Alloc> data;
size_t w, h; size_t w, h;
std::function<Type()> get_default_value_function=nullptr;
public: public:
using value_type = Type; using value_type = Type;
class row_ref { class row_ref {
@@ -30,10 +32,14 @@ public:
row_ref(vector2d<Type, Alloc>& ref, size_t row) : ref(ref), y(row) {} row_ref(vector2d<Type, Alloc>& ref, size_t row) : ref(ref), y(row) {}
public: public:
Type& operator[](size_t x) { Type& operator[](size_t x) {
return ref.data[ref.w * y + x]; if (x<ref.w)
return ref.data[ref.w * y + x];
return ref.get_bad_value();
} }
const Type& operator[](size_t x) const { const Type& operator[](size_t x) const {
return ref.data[ref.w * y + x]; if (x<ref.w)
return ref.data[ref.w * y + x];
return ref.get_bad_value();
} }
row_ref operator=(row_ref&& other) { row_ref operator=(row_ref&& other) {
row_ref& me = *this; row_ref& me = *this;
@@ -60,10 +66,14 @@ public:
col_ref(vector2d<Type, Alloc>& ref, size_t col) : ref(ref), x(col) {} col_ref(vector2d<Type, Alloc>& ref, size_t col) : ref(ref), x(col) {}
public: public:
Type& operator[](size_t y) { Type& operator[](size_t y) {
return ref.data[ref.w * y + x]; if (y<ref.h)
return ref.data[ref.w * y + x];
return ref.get_bad_value();
} }
const Type& operator[](size_t y) const { const Type& operator[](size_t y) const {
return ref.data[ref.w * y + x]; if (y<ref.h)
return ref.data[ref.w * y + x];
return ref.get_bad_value();
} }
col_ref operator=(col_ref&& other) { col_ref operator=(col_ref&& other) {
col_ref& me = *this; col_ref& me = *this;
@@ -90,7 +100,9 @@ public:
const_row_ref(const vector2d<Type, Alloc>& ref, size_t row) : ref(ref), y(row) {} const_row_ref(const vector2d<Type, Alloc>& ref, size_t row) : ref(ref), y(row) {}
public: public:
const Type& operator[](size_t x) const { const Type& operator[](size_t x) const {
return ref.data[ref.w * y + x]; if (x<ref.w)
return ref.data[ref.w * y + x];
return ref.get_bad_value();
} }
}; };
class const_col_ref { class const_col_ref {
@@ -100,32 +112,50 @@ public:
const_col_ref(const vector2d<Type, Alloc>& ref, size_t col) : ref(ref), x(col) {} const_col_ref(const vector2d<Type, Alloc>& ref, size_t col) : ref(ref), x(col) {}
public: public:
const Type& operator[](size_t y) const { const Type& operator[](size_t y) const {
return ref.data[ref.w * y + x]; if (y<ref.h)
return ref.data[ref.w * y + x];
return ref.get_bad_value();
} }
}; };
col_ref operator[](size_t x) { col_ref operator[](size_t x) {
return col_ref(*this, x); if (x<w)
return col_ref(*this, x);
return get_bad_vector()[0];
} }
const_col_ref operator[](size_t x) const { const_col_ref operator[](size_t x) const {
return const_col_ref(*this, x); if (x<w)
return const_col_ref(*this, x);
return get_bad_const_vector()[0];
} }
col_ref col(size_t x) { col_ref col(size_t x) {
return col_ref(*this, x); if (x<w)
return col_ref(*this, x);
return get_bad_vector()[0];
} }
const_col_ref col(size_t x) const { const_col_ref col(size_t x) const {
return const_col_ref(*this, x); if (x<w)
return const_col_ref(*this, x);
return get_bad_const_vector()[0];
} }
row_ref row(size_t x) { row_ref row(size_t y) {
return row_ref(*this, x); if (y<h)
return row_ref(*this, y);
return get_bad_vector().row(0);
} }
const_row_ref row(size_t x) const { const_row_ref row(size_t y) const {
return const_row_ref(*this, x); if (y<h)
return const_row_ref(*this, y);
return get_bad_const_vector().row(0);
} }
Type& operator()(size_t x, size_t y) { Type& operator()(size_t x, size_t y) {
return (*this)[x][y]; if (x<w && y<h)
return (*this)[x][y];
return get_bad_value();
} }
const Type& operator()(size_t x, size_t y) const { const Type& operator()(size_t x, size_t y) const {
return (*this)[x][y]; if (x<w && y<h)
return (*this)[x][y];
return get_bad_value();
} }
size_t width() const { size_t width() const {
return w; return w;
@@ -173,6 +203,32 @@ public:
vector2d(size_t w, size_t h) : w(w), h(h) { vector2d(size_t w, size_t h) : w(w), h(h) {
resize(w,h); resize(w,h);
} }
Type &get_bad_value() {
static Type badValue;
badValue=get_default_value_function ? get_default_value_function() : Type(-1);
return badValue;
}
const Type &get_bad_value() const {
static Type badValue;
badValue = get_default_value_function ? get_default_value_function() : Type(-1);
return badValue;
}
vector2d &get_bad_vector() {
static vector2d bad_vector(1,1);
bad_vector.data[0]=get_bad_value();
bad_vector.set_get_default_function(get_default_value_function);
return bad_vector;
}
vector2d const &get_bad_const_vector() const {
static vector2d bad_vector(1,1);
bad_vector.data[0]=get_bad_value();
bad_vector.set_get_default_function(get_default_value_function);
return bad_vector;
}
void set_get_default_function(std::function<Type()> const &func) {
get_default_value_function=func;
}
}; };
#endif #endif