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:
parent
9f379b96e3
commit
4d0fbc1d4e
7 changed files with 32 additions and 11 deletions
|
@ -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);
|
||||
|
|
|
@ -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_) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue