Add sanity-checking for WML attribute/tag/variable names to prevent invalid save files
- It's now an error to set an invalid variable - If an invalid key or tag is somehow set, it won't be written to the file (with an error message in the log) - There's an API function config::valid_id() which can be used to catch issues earlier.
This commit is contained in:
parent
e9be2324b5
commit
af2e16f842
4 changed files with 30 additions and 6 deletions
|
@ -480,6 +480,19 @@ config &config::operator=(config &&cfg)
|
|||
}
|
||||
#endif
|
||||
|
||||
bool config::valid_id(const std::string id)
|
||||
{
|
||||
if (id.empty()) {
|
||||
return false;
|
||||
}
|
||||
BOOST_FOREACH(char c, id) {
|
||||
if (!isalnum(c) && c != '_') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool config::has_attribute(const std::string &key) const
|
||||
{
|
||||
check_valid();
|
||||
|
|
|
@ -103,7 +103,9 @@ public:
|
|||
explicit config(const std::string &child);
|
||||
|
||||
~config();
|
||||
|
||||
|
||||
// Verifies that the string can be used as an attribute or tag name
|
||||
static bool valid_id(std::string);
|
||||
|
||||
#ifdef HAVE_CXX11
|
||||
explicit operator bool() const
|
||||
|
|
|
@ -581,11 +581,19 @@ static void write_internal(config const &cfg, std::ostream &out, std::string& te
|
|||
throw config::error("Too many recursion levels in config write");
|
||||
|
||||
BOOST_FOREACH(const config::attribute &i, cfg.attribute_range()) {
|
||||
if (!config::valid_id(i.first)) {
|
||||
ERR_CF << "Config contains invalid attribute name '" << i.first << "', skipping...\n";
|
||||
continue;
|
||||
}
|
||||
write_key_val(out, i.first, i.second, tab, textdomain);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const config::any_child &item, cfg.all_children_range())
|
||||
{
|
||||
if (!config::valid_id(item.key)) {
|
||||
ERR_CF << "Config contains invalid tag name '" << item.key << "', skipping...\n";
|
||||
continue;
|
||||
}
|
||||
write_open_child(out, item.key, tab);
|
||||
write_internal(item.cfg, out, textdomain, tab + 1);
|
||||
write_close_child(out, item.key, tab);
|
||||
|
|
|
@ -170,10 +170,7 @@ namespace
|
|||
char* endptr;
|
||||
int res = strtol(index_str, &endptr, 10);
|
||||
|
||||
if (*endptr != ']') {
|
||||
res = 0;//default
|
||||
}
|
||||
if(res > int(game_config::max_loop))
|
||||
if (*endptr != ']' || res > int(game_config::max_loop))
|
||||
{
|
||||
throw invalid_variablename_exception();
|
||||
}
|
||||
|
@ -186,7 +183,11 @@ namespace
|
|||
: public variable_info_visitor<vit, void>
|
||||
{
|
||||
public:
|
||||
get_variable_key_visitor(const std::string& key) : key_(key) {}
|
||||
get_variable_key_visitor(const std::string& key) : key_(key) {
|
||||
if (!config::valid_id(key_)) {
|
||||
throw invalid_variablename_exception();
|
||||
}
|
||||
}
|
||||
void from_named(typename get_variable_key_visitor::param_type state) const
|
||||
{
|
||||
if(key_ == "length")
|
||||
|
|
Loading…
Add table
Reference in a new issue