attempt to fix crashes when units with invalid sides appear,

by rejecting such invalide sides in the unit's constructor
This commit is contained in:
Dave White 2004-05-07 15:03:59 +00:00
parent 8512b2a8de
commit 011244a19e
6 changed files with 44 additions and 6 deletions

View file

@ -635,6 +635,11 @@ int play_game(int argc, char** argv)
gui::show_dialog(disp,NULL,"",
string_table["bad_save_message"],gui::OK_ONLY);
continue;
} catch(gamestatus::game_error& e) {
std::cerr << "caught game_error\n";
gui::show_dialog(disp,NULL,"",
string_table["bad_save_message"],gui::OK_ONLY);
continue;
} catch(config::error& e) {
std::cerr << "caught config::error\n";
gui::show_dialog(disp,NULL,"",
@ -690,10 +695,12 @@ int play_game(int argc, char** argv)
play_level(units_data,game_config,&starting_pos,video,state,story);
recorder.clear();
} catch(gamestatus::load_game_failed& e) {
gui::show_dialog(disp,NULL,"","error loading the game: " + e.message,gui::OK_ONLY);
std::cerr << "error loading the game: " << e.message
<< "\n";
return 0;
} catch(gamestatus::game_error& e) {
gui::show_dialog(disp,NULL,"","error while playing the game: " + e.message,gui::OK_ONLY);
std::cerr << "error while playing the game: "
<< e.message << "\n";
return 0;

View file

@ -177,6 +177,10 @@ void find_routes(const gamemap& map, const gamestatus& status,
std::vector<team>& teams,
bool ignore_zocs, bool allow_teleport, int turns_left, bool starting_pos)
{
if(size_t(u.side()-1) >= teams.size()) {
return;
}
team& current_team = teams[u.side()-1];
//find adjacent tiles

View file

@ -162,6 +162,8 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
std::vector<team> teams;
const teams_manager team_manager(teams);
int first_human_team = -1;
const config::child_list& unit_cfg = level->get_children("side");
@ -193,6 +195,8 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
std::cerr << "set gold to '" << ngold << "'\n";
teams.push_back(team(**ui,ngold));
//if this side tag describes the leader of the side
if((**ui)["no_leader"] != "yes") {
unit new_unit(gameinfo, **ui);
@ -234,8 +238,6 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
}
}
teams.push_back(team(**ui,ngold));
//if the game state specifies units that can be recruited for the player
//then add them
if(teams.size() == 1 && state_of_game.can_recruit.empty() == false) {
@ -265,8 +267,6 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
}
}
const teams_manager team_manager(teams);
const config* theme_cfg = NULL;
if((*level)["theme"] != "") {
theme_cfg = game_config.find_child("theme","name",(*level)["theme"]);

View file

@ -368,10 +368,14 @@ const std::string& team::name() const
bool team::is_enemy(int n) const
{
const size_t index = size_t(n-1);
if(teams == NULL || index >= teams->size()) {
return false;
}
//if we have a team name, we are friends with anyone who has the same team name
if(info_.team_name.empty() == false) {
return teams != NULL && size_t(n-1) < teams->size() &&
(*teams)[n-1].info_.team_name != info_.team_name;
return (*teams)[index].info_.team_name != info_.team_name;
}
//if enemies aren't listed, then everyone is an enemy
@ -589,3 +593,15 @@ bool is_observer()
return true;
}
void validate_side(int side)
{
if(teams == NULL) {
return;
}
if(side < 1 || side > int(teams->size())) {
std::cerr << "invalid side " << side << " throwing game_error\n";
throw gamestatus::game_error("invalid side found in unit definition");
}
}

View file

@ -146,4 +146,8 @@ struct teams_manager {
bool is_observer();
//function which will validate a side. Throws gamestatus::game_error
//if the side is invalid
void validate_side(int side); //throw gamestatus::game_error
#endif

View file

@ -71,6 +71,9 @@ unit::unit(const unit_type* t, int side, bool use_traits) :
backupAttacks_(t->attacks()),
guardian_(false), upkeep_(UPKEEP_FULL_PRICE)
{
validate_side(side_);
if(use_traits) {
//units that don't have traits generated are just generic
//units, so they shouldn't get a description either.
@ -100,6 +103,8 @@ unit::unit(const unit_type* t, const unit& u) :
traitsDescription_(u.traitsDescription_),
guardian_(false), upkeep_(u.upkeep_)
{
validate_side(side_);
//apply modifications etc, refresh the unit
apply_modifications();
heal_all();
@ -541,6 +546,8 @@ void unit::read(game_data& data, const config& cfg)
if(side_ <= 0)
side_ = 1;
validate_side(side_);
description_ = cfg["user_description"];
underlying_description_ = cfg["description"];
if(description_ == "") {