From 15db88e72375f545c18469cb617ff852afc1c2ec Mon Sep 17 00:00:00 2001 From: ALONSO Laurent Date: Wed, 20 Oct 2021 15:00:22 +0200 Subject: [PATCH] all[special_items]: add a function to protect access from bad index... --- src/fileio/fileio_scen.cpp | 17 +++++++---------- src/game/boe.graphutil.cpp | 2 +- src/game/boe.infodlg.cpp | 3 +-- src/game/boe.specials.cpp | 2 +- src/game/boe.text.cpp | 4 ++-- src/scenario/scenario.cpp | 22 ++++++++++++++++++++++ src/scenario/scenario.hpp | 3 +++ src/scenedit/scen.actions.cpp | 6 +++--- src/scenedit/scen.core.cpp | 17 ++++++++--------- src/universe/universe.hpp | 2 ++ 10 files changed, 50 insertions(+), 28 deletions(-) diff --git a/src/fileio/fileio_scen.cpp b/src/fileio/fileio_scen.cpp index d350119e..09d07f6c 100644 --- a/src/fileio/fileio_scen.cpp +++ b/src/fileio/fileio_scen.cpp @@ -164,7 +164,7 @@ static void port_special_text_response(cSpecial &special, cScenario& scenario) auto &wh=step==0 ? special.ex1a : special.ex2a; if (wh>=-100 && wh<0) { // (60-159)-160 int item=(wh+100)/2; - if (item < scenario.special_items.size()) { + if (item>=0 && item < scenario.special_items.size()) { wh=scenario.spec_strs.size(); scenario.spec_strs.push_back((wh%2 == 0) ? scenario.special_items[item].name : scenario.special_items[item].descr); } @@ -833,7 +833,7 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) { "num-towns", "out-width", "out-height", "start-town", "town-start", "outdoor-start", "sector-start", }; Iterator game; - int store_rects = 0, town_mods = 0, spec_items = 0, quests = 0, shops = 0, timers = 0, strnum; + int store_rects = 0, town_mods = 0, timers = 0, strnum; for(game = game.begin(elem.Get()); game != game.end(); game++) { game->GetValue(&type); reqs.erase(type); @@ -874,16 +874,13 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) { town_mods++; } else if(type == "special-item") { scenario.special_items.emplace_back(); - readSpecItemFromXml(*game, scenario.special_items[spec_items]); - spec_items++; + readSpecItemFromXml(*game, scenario.special_items.back()); } else if(type == "quest") { scenario.quests.emplace_back(); - readQuestFromXml(*game, scenario.quests[quests]); - quests++; + readQuestFromXml(*game, scenario.quests.back()); } else if(type == "shop") { scenario.shops.emplace_back(); - readShopFromXml(*game, scenario.shops[shops]); - shops++; + readShopFromXml(*game, scenario.shops.back()); } else if(type == "timer") { if(timers >= 20) throw xBadNode(type,game->Row(),game->Column(),fname); @@ -891,12 +888,12 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) { timers++; } else if(type == "string") { game->GetAttribute("id", &strnum); - if(strnum >= scenario.spec_strs.size()) + if(strnum >= scenario.spec_strs.size()) // changeme: add a maximum and discard data if not in a range scenario.spec_strs.resize(strnum + 1); game->GetText(&scenario.spec_strs[strnum], false); } else if(type == "journal") { game->GetAttribute("id", &strnum); - if(strnum >= scenario.journal_strs.size()) + if(strnum >= scenario.journal_strs.size()) // changeme: add a maximum and discard data if not in a range scenario.journal_strs.resize(strnum + 1); game->GetText(&scenario.journal_strs[strnum], false); } else throw xBadNode(type, game->Row(), game->Column(), fname); diff --git a/src/game/boe.graphutil.cpp b/src/game/boe.graphutil.cpp index dbf30422..50dde52a 100644 --- a/src/game/boe.graphutil.cpp +++ b/src/game/boe.graphutil.cpp @@ -74,7 +74,7 @@ void draw_one_terrain_spot (short i,short j,short terrain_to_draw) { Texture source_gworld; cPictNum pict; if (terrain_to_draw>=10000) // force using a specific graphic - pict=cPictNum(terrain_to_draw-10000,ePicType::PIC_TER); + pict=cTerrain::get_picture_num_for_terrain(terrain_to_draw-10000); else pict=univ.get_terrain(terrain_to_draw).get_picture_num(); if (!cPict::get_picture(pict, source_gworld, source_rect, anim_ticks % 4)) { diff --git a/src/game/boe.infodlg.cpp b/src/game/boe.infodlg.cpp index aa2093ef..eebc88dc 100644 --- a/src/game/boe.infodlg.cpp +++ b/src/game/boe.infodlg.cpp @@ -679,8 +679,7 @@ void put_quest_info(short which_i) { } void put_spec_item_info (short which_i) { - cStrDlog display_strings(univ.scenario.special_items[which_i].descr,"", - univ.scenario.special_items[which_i].name,univ.scenario.intro_pic,PIC_SCEN); + cStrDlog display_strings(univ.get_special_item(which_i).descr,"",univ.get_special_item(which_i).name,univ.scenario.intro_pic,PIC_SCEN); display_strings.setSound(57); display_strings.show(); } diff --git a/src/game/boe.specials.cpp b/src/game/boe.specials.cpp index 8b7cbc8e..93bada49 100644 --- a/src/game/boe.specials.cpp +++ b/src/game/boe.specials.cpp @@ -585,7 +585,7 @@ void check_fields(location where_check,eSpecCtx mode,cPlayer& which_pc) { } void use_spec_item(short item) { - run_special(eSpecCtx::USE_SPEC_ITEM, eSpecCtxType::SCEN, univ.scenario.special_items[item].special, univ.party.get_loc()); + run_special(eSpecCtx::USE_SPEC_ITEM, eSpecCtxType::SCEN, univ.get_special_item(item).special, univ.party.get_loc()); } diff --git a/src/game/boe.text.cpp b/src/game/boe.text.cpp index 21bb8c2e..9e4b9544 100644 --- a/src/game/boe.text.cpp +++ b/src/game/boe.text.cpp @@ -258,10 +258,10 @@ void put_item_screen(eItemWinMode screen_num) { for(short i = 0; i < 8; i++) { i_num = i + item_offset; if(i_num < spec_item_array.size()) { - win_draw_string(item_stats_gworld,item_buttons[i][ITEMBTN_NAME],univ.scenario.special_items[spec_item_array[i_num]].name,eTextMode::WRAP,style); + win_draw_string(item_stats_gworld,item_buttons[i][ITEMBTN_NAME],univ.get_special_item(spec_item_array[i_num]).name,eTextMode::WRAP,style); place_item_button(3,i,ITEMBTN_INFO); - if((univ.scenario.special_items[spec_item_array[i_num]].flags % 10 == 1) + if((univ.get_special_item(spec_item_array[i_num]).flags % 10 == 1) && (!(is_combat()))) place_item_button(0,i,ITEMBTN_USE); } diff --git a/src/scenario/scenario.cpp b/src/scenario/scenario.cpp index 05fc2bf5..a3a86f2f 100644 --- a/src/scenario/scenario.cpp +++ b/src/scenario/scenario.cpp @@ -235,6 +235,28 @@ cItem &cScenario::get_item(item_num_t item) return badItem; } +static cSpecItem getBadSpecialItem() { + cSpecItem badItem; + badItem.name="Bad Special Item"; + return badItem; +} + +cSpecItem const &cScenario::get_special_item(item_num_t item) const +{ + if (item>=0 && item=0 && item(me["usable"]).getState() != led_off) item.flags += 1; - scenario.special_items[which] = item; + scenario.get_special_item(which) = item; return true; } @@ -2002,13 +2002,13 @@ static bool edit_spec_item_event_filter(cDialog& me, std::string hit, cSpecItem& if(!save_spec_item(me, item, which)) return true; which--; if(which < 0) which = scenario.special_items.size() - 1; - item = scenario.special_items[which]; + item = scenario.get_special_item(which); put_spec_item_in_dlog(me, item, which); } else if(hit == "right") { if(!save_spec_item(me, item, which)) return true; which++; if(which >= scenario.special_items.size()) which = 0; - item = scenario.special_items[which]; + item = scenario.get_special_item(which); put_spec_item_in_dlog(me, item, which); } else if(hit == "edit-spec") { if(!save_spec_item(me, item, which)) return true; @@ -2026,20 +2026,20 @@ static bool edit_spec_item_event_filter(cDialog& me, std::string hit, cSpecItem& bool edit_spec_item(short which_item) { short first = which_item; using namespace std::placeholders; - cSpecItem item = scenario.special_items[which_item]; + cSpecItem &item = scenario.get_special_item(first); cDialog item_dlg("edit-special-item"); item_dlg["spec"].attachFocusHandler(std::bind(check_range_msg, _1, _2, _3, -1, scenario.scen_specials.size(), "Scenario special node called", "-1 for no special")); - item_dlg.attachClickHandlers(std::bind(edit_spec_item_event_filter, _1, _2, std::ref(item), std::ref(which_item)), {"okay", "cancel", "clear", "edit-spec"}); + item_dlg.attachClickHandlers(std::bind(edit_spec_item_event_filter, _1, _2, std::ref(item), std::ref(first)), {"okay", "cancel", "clear", "edit-spec"}); if(scenario.special_items.size() == 1) { item_dlg["left"].hide(); item_dlg["right"].hide(); } else { - item_dlg.attachClickHandlers(std::bind(edit_spec_item_event_filter, _1, _2, std::ref(item), std::ref(which_item)), {"left", "right"}); + item_dlg.attachClickHandlers(std::bind(edit_spec_item_event_filter, _1, _2, std::ref(item), std::ref(first)), {"left", "right"}); } - put_spec_item_in_dlog(item_dlg, item, which_item); + put_spec_item_in_dlog(item_dlg, item, first); item_dlg["clear"].hide(); item_dlg.run(); @@ -3174,7 +3174,6 @@ static bool edit_scenario_events_event_filter(cDialog& me, std::string item_hit, void edit_scenario_events() { using namespace std::placeholders; - size_t first_item = 0; size_t const num_items=9; ::cTimersState state(9); state.timers.insert(state.timers.begin(), scenario.scenario_timers.begin(), scenario.scenario_timers.end()); diff --git a/src/universe/universe.hpp b/src/universe/universe.hpp index 97ddc694..f2c9cdc9 100644 --- a/src/universe/universe.hpp +++ b/src/universe/universe.hpp @@ -217,6 +217,8 @@ public: cItem const &get_item(item_num_t item) const { return scenario.get_item(item); } cItem &get_item(item_num_t item) { return scenario.get_item(item); } + cSpecItem const &get_special_item(item_num_t item) const { return scenario.get_special_item(item); } + cSpecItem &get_special_item(item_num_t item) { return scenario.get_special_item(item); } cTerrain const &get_terrain(ter_num_t ter) const { return scenario.get_terrain(ter); } cTerrain &get_terrain(ter_num_t ter) { return scenario.get_terrain(ter); }