From afb3fec155fc7c4035dcb9c9cd6e411c8e2e0410 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Sat, 17 May 2014 15:23:02 -0400 Subject: [PATCH] catch bad lexical casts (from parsing map locations from configs) --- src/actions/undo.cpp | 29 ++++++++++++++++++++++------- src/actions/undo.hpp | 1 + src/game_events/action_wml.cpp | 11 +++++++++-- src/map_location.hpp | 6 +++++- src/playsingle_controller.cpp | 10 ++++++++-- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/actions/undo.cpp b/src/actions/undo.cpp index d2965c164f9..669b6090045 100644 --- a/src/actions/undo.cpp +++ b/src/actions/undo.cpp @@ -236,12 +236,13 @@ undo_list::undo_action::create(const config & cfg, const std::string & tag) // constructors will parse the "unit" child config, while this function // parses everything else. - if ( str == "move" ) + if ( str == "move" ) { res = new move_action(cfg.child("unit", tag), cfg, cfg["starting_moves"], cfg["time_bonus"], cfg["village_owner"], map_location::parse_direction(cfg["starting_direction"])); + } if ( str == "recruit" ) { // Validate the unit type. @@ -532,16 +533,30 @@ void undo_list::read(const config & cfg) // Build the undo stack. BOOST_FOREACH( const config & child, cfg.child_range("undo") ) { - undo_action * action = undo_action::create(child, "[undo]"); - if ( action ) - undos_.push_back(action); + try { + undo_action * action = undo_action::create(child, "[undo]"); + if ( action ) { + undos_.push_back(action); + } + } catch (bad_lexical_cast &) { + ERR_NG << "Error when parsing undo list from config: bad lexical cast." << std::endl; + ERR_NG << "config was: " << child.debug() << std::endl; + ERR_NG << "Skipping this undo action..." << std::endl; + } } // Build the redo stack. BOOST_FOREACH( const config & child, cfg.child_range("redo") ) { - undo_action * action = undo_action::create(child, "[redo]"); - if ( action ) - redos_.push_back(action); + try { + undo_action * action = undo_action::create(child, "[redo]"); + if ( action ) { + redos_.push_back(action); + } + } catch (bad_lexical_cast &) { + ERR_NG << "Error when parsing redo list from config: bad lexical cast." << std::endl; + ERR_NG << "config was: " << child.debug() << std::endl; + ERR_NG << "Skipping this redo action..." << std::endl; + } } } diff --git a/src/actions/undo.hpp b/src/actions/undo.hpp index 038867d70c2..ef55704fcf4 100644 --- a/src/actions/undo.hpp +++ b/src/actions/undo.hpp @@ -75,6 +75,7 @@ class undo_list : boost::noncopyable { /// Creates an undo_action based on a config. + /// Throws bad_lexical_cast if it cannot parse the config properly. static undo_action * create(const config & cfg, const std::string & tag); /// Writes this into the provided config. virtual void write(config & cfg) const = 0; diff --git a/src/game_events/action_wml.cpp b/src/game_events/action_wml.cpp index 97288d2b1b2..75ca236a391 100644 --- a/src/game_events/action_wml.cpp +++ b/src/game_events/action_wml.cpp @@ -2288,8 +2288,15 @@ WML_HANDLER_FUNCTION(set_variables, /*event_info*/, cfg) WML_HANDLER_FUNCTION(sound_source, /*event_info*/, cfg) { - soundsource::sourcespec spec(cfg.get_parsed_config()); - resources::soundsources->add(spec); + config parsed = cfg.get_parsed_config(); + try { + soundsource::sourcespec spec(parsed); + resources::soundsources->add(spec); + } catch (bad_lexical_cast &) { + ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl; + ERR_NG << "sound_source config was: " << parsed.debug() << std::endl; + ERR_NG << "Skipping this sound source..." << std::endl; + } } /// Store time of day config in a WML variable. This is useful for those who diff --git a/src/map_location.hpp b/src/map_location.hpp index c3303baef20..72c7878aec0 100644 --- a/src/map_location.hpp +++ b/src/map_location.hpp @@ -126,7 +126,11 @@ std::vector parse_location_range(const std::string& xvals, */ void write_location_range(const std::set& locs, config& cfg); -/** Parse x,y keys of a config into a vector of locations */ +/** + * Parse x,y keys of a config into a vector of locations + * + * Throws bad_lexical_cast if it fails to parse. + */ void read_locations(const config& cfg, std::vector& locs); /** Write a vector of locations into a config diff --git a/src/playsingle_controller.cpp b/src/playsingle_controller.cpp index a711fdc2cb3..6a3b0467dd5 100644 --- a/src/playsingle_controller.cpp +++ b/src/playsingle_controller.cpp @@ -359,8 +359,14 @@ LEVEL_RESULT playsingle_controller::play_scenario( // Read sound sources assert(soundsources_manager_ != NULL); BOOST_FOREACH(const config &s, level_.child_range("sound_source")) { - soundsource::sourcespec spec(s); - soundsources_manager_->add(spec); + try { + soundsource::sourcespec spec(s); + soundsources_manager_->add(spec); + } catch (bad_lexical_cast &) { + ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl; + ERR_NG << "sound_source config was: " << s.debug() << std::endl; + ERR_NG << "Skipping this sound source..." << std::endl; + } } set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true));