summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2008-05-04 21:36:37 +0000
committerrubidium <rubidium@openttd.org>2008-05-04 21:36:37 +0000
commit762315c47cd539dc5a7288803ad4d6dd613e17b8 (patch)
tree4098bb276386f0bec0483a6d5ec23a8baad927e3
parentcb680474c3c1f58772533e257c6acbbf4e13c524 (diff)
downloadopenttd-762315c47cd539dc5a7288803ad4d6dd613e17b8.tar.xz
(svn r12942) -Fix [FS#1979]: closing some windows caused recursion in the Window deletion causing the reading invalid/freed data which could cause crashes.
-rw-r--r--src/window.cpp30
1 files changed, 16 insertions, 14 deletions
diff --git a/src/window.cpp b/src/window.cpp
index daceb5406..597542275 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -416,35 +416,37 @@ void DeleteWindow(Window *w)
{
if (w == NULL) return;
- /* Delete any children a window might have in a head-recursive manner */
- Window *v = FindChildWindow(w);
- if (v != NULL) DeleteWindow(v);
-
if (_thd.place_mode != VHM_NONE &&
_thd.window_class == w->window_class &&
_thd.window_number == w->window_number) {
ResetObjectToPlace();
}
- CallWindowEventNP(w, WE_DESTROY);
- if (w->viewport != NULL) DeleteWindowViewport(w);
-
- SetWindowDirty(w);
- free(w->widget);
- w->widget = NULL;
- w->widget_count = 0;
- w->parent = NULL;
-
/* Prevent Mouseover() from resetting mouse-over coordinates on a non-existing window */
if (_mouseover_last_w == w) _mouseover_last_w = NULL;
/* Find the window in the z-array, and effectively remove it
- * by moving all windows after it one to the left */
+ * by moving all windows after it one to the left. This must be
+ * done before removing the child so we cannot cause recursion
+ * between the deletion of the parent and the child. */
Window **wz = FindWindowZPosition(w);
if (wz == NULL) return;
memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz);
_last_z_window--;
+ /* Delete any children a window might have in a head-recursive manner */
+ Window *v = FindChildWindow(w);
+ if (v != NULL) DeleteWindow(v);
+
+ CallWindowEventNP(w, WE_DESTROY);
+ if (w->viewport != NULL) DeleteWindowViewport(w);
+
+ SetWindowDirty(w);
+ free(w->widget);
+ w->widget = NULL;
+ w->widget_count = 0;
+ w->parent = NULL;
+
delete w;
}