diff options
author | rubidium <rubidium@openttd.org> | 2008-05-04 21:36:37 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2008-05-04 21:36:37 +0000 |
commit | 4acb8f3a5ee5a4262595a09591d14febcfe1c2ef (patch) | |
tree | 4098bb276386f0bec0483a6d5ec23a8baad927e3 /src | |
parent | 0083ce9e1b1af3ef49368af454c861e778472ac2 (diff) | |
download | openttd-4acb8f3a5ee5a4262595a09591d14febcfe1c2ef.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.
Diffstat (limited to 'src')
-rw-r--r-- | src/window.cpp | 30 |
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; } |