attempt to fix UB in tree_view and unit drawer.

since the treeview nodes are not owned by the treeview but by the
content grid, they get destroyed after the treeview so accesing the
treeview in the nodes dtor might result in UB.

Also UB happend in playsingle_controller and unit_drawer::unit_drawer
in case that the teams vector was empty.
This commit is contained in:
gfgtdf 2016-09-20 22:41:45 +02:00
parent 9f379b96e3
commit 4d0fbc1d4e
7 changed files with 32 additions and 11 deletions

View file

@ -42,7 +42,7 @@ public:
const_iterator begin() const { return fake_units_.begin(); }
const_iterator end() const { return fake_units_.end(); }
bool empty() const { return fake_units_.empty(); }
private:
/** Register a unit with this manager. private, should only be called by fake_unit_ptr. */
void place_temporary_unit(internal_ptr_type);

View file

@ -269,7 +269,9 @@ void game_display::draw_invalidated()
{
halo_man_->unrender(invalidated_);
display::draw_invalidated();
if (fake_unit_man_->empty()) {
return;
}
unit_drawer drawer = unit_drawer(*this, energy_bar_rects_);
for (const unit* temp_unit : *fake_unit_man_) {

View file

@ -54,7 +54,12 @@ ttree_view::ttree_view(const std::vector<tnode_definition>& node_definitions)
std::bind(&ttree_view::signal_handler_left_button_down, this, _2),
event::tdispatcher::back_pre_child);
}
ttree_view::~ttree_view()
{
if (root_node_) {
root_node_->clear_before_destruct();
}
}
ttree_view_node& ttree_view::add_node(
const std::string& id,
const std::map<std::string /* widget id */, string_map>& data)

View file

@ -46,6 +46,8 @@ public:
explicit ttree_view(const std::vector<tnode_definition>& node_definitions);
~ttree_view();
using tscrollbar_container::finalize_setup;
ttree_view_node& get_root_node()

View file

@ -40,7 +40,7 @@ ttree_view_node::ttree_view_node(
const std::map<std::string /* widget id */, string_map>& data)
: twidget()
, parent_node_(parent_node)
, tree_view_(parent_tree_view)
, tree_view_(&parent_tree_view)
, grid_()
, children_()
, node_definitions_(node_definitions)
@ -128,10 +128,17 @@ ttree_view_node::ttree_view_node(
ttree_view_node::~ttree_view_node()
{
if(/*tree_view() &&*/ tree_view().selected_item_ == this) {
if(tree_view_ && tree_view().selected_item_ == this) {
tree_view().selected_item_ = nullptr;
}
}
void ttree_view_node::clear_before_destruct()
{
tree_view_ = nullptr;
for (auto& child : children_) {
child.clear_before_destruct();
}
}
ttree_view_node& ttree_view_node::add_child(
const std::string& id,
@ -204,7 +211,7 @@ const ttree_view_node& ttree_view_node::parent_node() const
ttree_view& ttree_view_node::tree_view()
{
return tree_view_;
return *tree_view_;
}
void ttree_view_node::request_reduce_width(const unsigned /*maximum_width*/)
@ -214,7 +221,7 @@ void ttree_view_node::request_reduce_width(const unsigned /*maximum_width*/)
const ttree_view& ttree_view_node::tree_view() const
{
return tree_view_;
return *tree_view_;
}
bool ttree_view_node::is_folded() const

View file

@ -221,6 +221,9 @@ public:
void select_node();
tgrid& get_grid() { return grid_; }
void layout_initialise(const bool full_initialisation) override;
void clear_before_destruct();
private:
int calculate_ypos();
@ -235,7 +238,7 @@ private:
ttree_view_node* parent_node_;
/** The tree view that owns us. */
ttree_view& tree_view_;
ttree_view* tree_view_;
/** Grid holding our contents. */
tgrid grid_;

View file

@ -620,10 +620,12 @@ void playsingle_controller::force_end_turn(){
void playsingle_controller::check_objectives()
{
const team &t = gamestate().board_.teams()[gui_->viewing_team()];
if (!gamestate().board_.teams().empty()) {
const team &t = gamestate().board_.teams()[gui_->viewing_team()];
if (!is_regular_game_end() && !is_browsing() && t.objectives_changed()) {
show_objectives();
if (!is_regular_game_end() && !is_browsing() && t.objectives_changed()) {
show_objectives();
}
}
}