make unit filters a little more safe against nullptr access.

This commit is contained in:
gfgtdf 2018-10-25 23:29:34 +02:00
parent cc5aac7009
commit e634198a5e
2 changed files with 27 additions and 13 deletions

View file

@ -103,7 +103,7 @@ struct unit_filter_xy : public unit_filter_base
return false;
}
else if(x == "recall" && y == "recall") {
return !args.fc->get_disp_context().map().on_board(args.loc);
return !args.context().get_disp_context().map().on_board(args.loc);
}
else {
return args.loc.matches_range(x, y);
@ -124,7 +124,7 @@ struct unit_filter_adjacent : public unit_filter_base
virtual bool matches(const unit_filter_args& args) const override
{
const unit_map& units = args.fc->get_disp_context().units();
const unit_map& units = args.context().get_disp_context().units();
adjacent_loc_array_t adjacent;
get_adjacent_tiles(args.loc, adjacent.data());
int match_count=0;
@ -142,7 +142,7 @@ struct unit_filter_adjacent : public unit_filter_base
continue;
}
auto is_enemy = cfg_["is_enemy"];
if (!is_enemy.empty() && is_enemy.to_bool() != args.fc->get_disp_context().get_team(args.u.side()).is_enemy(unit_itor->side())) {
if (!is_enemy.empty() && is_enemy.to_bool() != args.context().get_disp_context().get_team(args.u.side()).is_enemy(unit_itor->side())) {
continue;
}
++match_count;
@ -229,10 +229,10 @@ bool unit_filter_compound::matches(const unit_filter_args& args) const
bool res;
if(args.loc.valid()) {
scoped_xy_unit auto_store("this_unit", args.u.get_location(), args.fc->get_disp_context().units());
scoped_xy_unit auto_store("this_unit", args.u.get_location(), args.context().get_disp_context().units());
if (args.u2) {
const map_location& loc2 = args.u2->get_location();
scoped_xy_unit u2_auto_store("other_unit", loc2, args.fc->get_disp_context().units());
scoped_xy_unit u2_auto_store("other_unit", loc2, args.context().get_disp_context().units());
res = filter_impl(args);
} else {
res = filter_impl(args);
@ -555,7 +555,7 @@ void unit_filter_compound::fill(vconfig cfg)
[](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
[](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
{
int actual_defense = args.u.defense_modifier(args.fc->get_disp_context().map().get_terrain(args.loc));
int actual_defense = args.u.defense_modifier(args.context().get_disp_context().map().get_terrain(args.loc));
for(auto def : ranges) {
if(def.first <= actual_defense && actual_defense <= def.second) {
return true;
@ -569,7 +569,7 @@ void unit_filter_compound::fill(vconfig cfg)
[](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
[](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
{
int actual_cost = args.u.movement_cost(args.fc->get_disp_context().map().get_terrain(args.loc));
int actual_cost = args.u.movement_cost(args.context().get_disp_context().map().get_terrain(args.loc));
for(auto cost : ranges) {
if(cost.first <= actual_cost && actual_cost <= cost.second) {
return true;
@ -583,7 +583,7 @@ void unit_filter_compound::fill(vconfig cfg)
[](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
[](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
{
int actual_cost = args.u.vision_cost(args.fc->get_disp_context().map().get_terrain(args.loc));
int actual_cost = args.u.vision_cost(args.context().get_disp_context().map().get_terrain(args.loc));
for(auto cost : ranges) {
if(cost.first <= actual_cost && actual_cost <= cost.second) {
return true;
@ -597,7 +597,7 @@ void unit_filter_compound::fill(vconfig cfg)
[](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
[](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
{
int actual_cost = args.u.jamming_cost(args.fc->get_disp_context().map().get_terrain(args.loc));
int actual_cost = args.u.jamming_cost(args.context().get_disp_context().map().get_terrain(args.loc));
for(auto cost : ranges) {
if(cost.first <= actual_cost && actual_cost <= cost.second) {
return true;
@ -611,7 +611,7 @@ void unit_filter_compound::fill(vconfig cfg)
[](const config::attribute_value& c) { return c.str(); },
[](const std::string& lua_function, const unit_filter_args& args)
{
if (game_lua_kernel * lk = args.fc->get_lua_kernel()) {
if (game_lua_kernel * lk = args.context().get_lua_kernel()) {
return lk->run_filter(lua_function.c_str(), args.u);
}
return true;
@ -651,7 +651,7 @@ void unit_filter_compound::fill(vconfig cfg)
[](const std::string& find_in, const unit_filter_args& args)
{
// Allow filtering by searching a stored variable of units
if (const game_data * gd = args.fc->get_game_data()) {
if (const game_data * gd = args.context().get_game_data()) {
try
{
for (const config& c : gd->get_variable_access_read(find_in).as_array())
@ -704,8 +704,8 @@ void unit_filter_compound::fill(vconfig cfg)
viewers.insert(sides.begin(), sides.end());
for (const int viewer : viewers) {
bool fogged = args.fc->get_disp_context().get_team(viewer).fogged(args.loc);
bool hiding = args.u.invisible(args.loc) && args.fc->get_disp_context().get_team(viewer).is_enemy(args.u.side());
bool fogged = args.context().get_disp_context().get_team(viewer).fogged(args.loc);
bool hiding = args.u.invisible(args.loc) && args.context().get_disp_context().get_team(viewer).is_enemy(args.u.side());
bool unit_hidden = fogged || hiding;
if (c["visible"].to_bool(true) != unit_hidden) {
return true;

View file

@ -51,6 +51,13 @@ namespace unit_filter_impl
(OR, "or")
(NOT, "not")
)
struct filter_error : public game::error
{
explicit filter_error(const std::string& message = "filter error")
: game::error(message)
{
}
};
struct unit_filter_args
{
@ -60,6 +67,13 @@ namespace unit_filter_impl
const filter_context* fc;
bool use_flat_tod;
const filter_context& context() const
{
if(fc) {
return *fc;
}
throw filter_error();
}
// This constructor is here to shut down warnings that the default constructor couldn't be generated.
// It's technically unnecessary since lacking of a default constructor doesn't prevent aggregate-initialization, but...
unit_filter_args(const unit& u, map_location loc, const unit* u2, const filter_context* fc, bool use_flat_tod)