mirror of
https://github.com/wesnoth/wesnoth
synced 2025-04-25 00:06:04 +00:00
Refuse to save if game state can't be represented as valid WML (#2375)
Such a save file can't be loaded anyway. This way, at least the player can't overwrite an existing, working save with one that cannot be loaded.
This commit is contained in:
parent
5df406869a
commit
3bc36efa58
@ -25,10 +25,12 @@
|
||||
#include "utils/const_clone.hpp"
|
||||
#include "utils/functional.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <istream>
|
||||
#include <locale>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
@ -1303,6 +1305,33 @@ void swap(config& lhs, config& rhs)
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
bool config::is_valid_wml_tag_name(config_key_type name)
|
||||
{
|
||||
if(name == "") {
|
||||
// Empty strings not allowed
|
||||
return false;
|
||||
} else if(name[0] == '_') {
|
||||
// Underscore can't be the first character
|
||||
return false;
|
||||
} else {
|
||||
return std::all_of(name.begin(), name.end(), [](const char& c)
|
||||
{
|
||||
// Only alphanumeric ASCII characters and underscores are allowed
|
||||
return std::isalnum(static_cast<unsigned char>(c), std::locale::classic()) || c == '_';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool config::validate_wml() const
|
||||
{
|
||||
return std::all_of(children_.begin(), children_.end(), [](const child_map::value_type& pair)
|
||||
{
|
||||
return is_valid_wml_tag_name(pair.first) &&
|
||||
std::all_of(pair.second.begin(), pair.second.end(),
|
||||
[](const std::unique_ptr<config>& c) { return c->validate_wml(); });
|
||||
});
|
||||
}
|
||||
|
||||
bool operator==(const config& a, const config& b)
|
||||
{
|
||||
a.check_valid(b);
|
||||
|
@ -761,6 +761,17 @@ public:
|
||||
//this is a cheap O(1) operation
|
||||
void swap(config& cfg);
|
||||
|
||||
/**
|
||||
* Returns true for valid WML tag names, false for all other strings.
|
||||
*/
|
||||
static bool is_valid_wml_tag_name(config_key_type name);
|
||||
|
||||
/**
|
||||
* Returns true if this object represents valid WML,
|
||||
* i.e. can be saved to disk and again loaded by the WML parser.
|
||||
*/
|
||||
bool validate_wml() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Removes the child at position @a pos of @a l.
|
||||
|
@ -637,6 +637,10 @@ void ingame_savegame::create_filename()
|
||||
void ingame_savegame::write_game(config_writer &out) {
|
||||
log_scope("write_game");
|
||||
|
||||
if(!gamestate().get_starting_pos().validate_wml()) {
|
||||
throw game::save_game_failed(_("Game state is corrupted"));
|
||||
}
|
||||
|
||||
savegame::write_game(out);
|
||||
|
||||
gamestate().write_carryover(out);
|
||||
|
Loading…
x
Reference in New Issue
Block a user