From 74b3b45c61a41300c2e84201f813817eada27351 Mon Sep 17 00:00:00 2001 From: Thierry Crozat Date: Sat, 22 Oct 2016 21:31:39 +0100 Subject: GUI: Fix possible access to free'ed memory or double deletion in tab widget The issue could occur when adding or removing widgets to a tab, and then not switching to a different tab before the destructor or reflowLayout() were called. In such a case the firstWidget of the current widget in the _tabs list could be out of date. Accessing this first widget from the destructor or from reflowLayout() could then cause a crash, or random issues caused to access to free'ed memory. In theory this could also lead to a memory leak, although I don't think this could occur in our current code. Usually we add several tabs to a TabWidget and then switch back to the first tab after building all the tabs. So in such a case the issue would not occur. But because we are deleting and reconstructing the clear buttons for the MIDI and Path tabs of the options dialog from reflowLayout(), if the current tab is the Path tab, it would be kept as active tab after adding and removing widget to it and the issue would occur. This fixes bug #9618. --- gui/widgets/tab.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'gui/widgets') diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp index 15e6a9d370..ed261c98ec 100644 --- a/gui/widgets/tab.cpp +++ b/gui/widgets/tab.cpp @@ -70,6 +70,12 @@ void TabWidget::init() { } TabWidget::~TabWidget() { + // If widgets were added or removed in the current tab, without tabs + // having been switched using setActiveTab() afterward, then the + // firstWidget in the _tabs list for the active tab may not be up to + // date. So update it now. + if (_activeTab != -1) + _tabs[_activeTab].firstWidget = _firstWidget; _firstWidget = 0; for (uint i = 0; i < _tabs.size(); ++i) { delete _tabs[i].firstWidget; @@ -274,6 +280,13 @@ void TabWidget::reflowLayout() { _tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width"); _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top"); + // If widgets were added or removed in the current tab, without tabs + // having been switched using setActiveTab() afterward, then the + // firstWidget in the _tabs list for the active tab may not be up to + // date. So update it now. + if (_activeTab != -1) + _tabs[_activeTab].firstWidget = _firstWidget; + for (uint i = 0; i < _tabs.size(); ++i) { Widget *w = _tabs[i].firstWidget; while (w) { -- cgit v1.2.3