mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-16 00:12:51 +00:00
(svn r14905) -Fix (r14899): in some corner cases already freed memory could be read.
This commit is contained in:
parent
6bd14cf1a1
commit
c71862174a
@ -219,8 +219,7 @@ static Point _vp_move_offs;
|
||||
|
||||
static void DoSetViewportPosition(const Window *w, int left, int top, int width, int height)
|
||||
{
|
||||
|
||||
for (; w != NULL; w = w->z_front) {
|
||||
FOR_ALL_WINDOWS_FROM_BACK_FROM(w, w) {
|
||||
if (left + width > w->left &&
|
||||
w->left + w->width > left &&
|
||||
top + height > w->top &&
|
||||
|
@ -296,7 +296,8 @@ static void DispatchMouseWheelEvent(Window *w, int widget, int wheel)
|
||||
*/
|
||||
static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom)
|
||||
{
|
||||
for (const Window *v = w->z_front; v != NULL; v = v->z_front) {
|
||||
const Window *v;
|
||||
FOR_ALL_WINDOWS_FROM_BACK_FROM(v, w->z_front) {
|
||||
if (right > v->left &&
|
||||
bottom > v->top &&
|
||||
left < v->left + v->width &&
|
||||
@ -427,21 +428,6 @@ Window::~Window()
|
||||
/* Prevent Mouseover() from resetting mouse-over coordinates on a non-existing window */
|
||||
if (_mouseover_last_w == this) _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. This must be
|
||||
* done before removing the child so we cannot cause recursion
|
||||
* between the deletion of the parent and the child. */
|
||||
if (this->z_front == NULL) {
|
||||
_z_front_window = this->z_back;
|
||||
} else {
|
||||
this->z_front->z_back = this->z_back;
|
||||
}
|
||||
if (this->z_back == NULL) {
|
||||
_z_back_window = this->z_front;
|
||||
} else {
|
||||
this->z_back->z_front = this->z_front;
|
||||
}
|
||||
|
||||
this->DeleteChildWindows();
|
||||
|
||||
if (this->viewport != NULL) DeleteWindowViewport(this);
|
||||
@ -454,6 +440,8 @@ Window::~Window()
|
||||
}
|
||||
free(this->widget);
|
||||
}
|
||||
|
||||
this->window_class = WC_INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1091,7 +1079,17 @@ void InitWindowSystem()
|
||||
*/
|
||||
void UnInitWindowSystem()
|
||||
{
|
||||
while (_z_front_window != NULL) delete _z_front_window;
|
||||
Window *w;
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) delete w;
|
||||
|
||||
for (w = _z_front_window; w != NULL; /* nothing */) {
|
||||
Window *to_del = w;
|
||||
w = w->z_back;
|
||||
free(to_del);
|
||||
}
|
||||
|
||||
_z_front_window = NULL;
|
||||
_z_back_window = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1583,7 +1581,8 @@ static bool MaybeBringWindowToFront(Window *w)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Window *u = w->z_front; u != NULL; u = u->z_front) {
|
||||
Window *u;
|
||||
FOR_ALL_WINDOWS_FROM_BACK_FROM(u, w->z_front) {
|
||||
/* A modal child will prevent the activation of the parent window */
|
||||
if (u->parent == w && (u->desc_flags & WDF_MODAL)) {
|
||||
u->flags4 |= WF_WHITE_BORDER_MASK;
|
||||
@ -1973,6 +1972,30 @@ void InputLoop()
|
||||
CheckSoftLimit();
|
||||
HandleKeyScrolling();
|
||||
|
||||
/* Do the actual free of the deleted windows. */
|
||||
for (Window *v = _z_front_window; v != NULL; /* nothing */) {
|
||||
Window *w = v;
|
||||
v = v->z_back;
|
||||
|
||||
if (w->window_class != WC_INVALID) continue;
|
||||
|
||||
/* Find the window in the z-array, and effectively remove it
|
||||
* 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. */
|
||||
if (w->z_front == NULL) {
|
||||
_z_front_window = w->z_back;
|
||||
} else {
|
||||
w->z_front->z_back = w->z_back;
|
||||
}
|
||||
if (w->z_back == NULL) {
|
||||
_z_back_window = w->z_front;
|
||||
} else {
|
||||
w->z_back->z_front = w->z_front;
|
||||
}
|
||||
free(w);
|
||||
}
|
||||
|
||||
if (_input_events_this_tick != 0) {
|
||||
/* The input loop is called only once per GameLoop() - so we can clear the counter here */
|
||||
_input_events_this_tick = 0;
|
||||
|
@ -203,6 +203,11 @@ public:
|
||||
Window(const WindowDesc *desc, WindowNumber number = 0);
|
||||
|
||||
virtual ~Window();
|
||||
/* Don't allow arrays; arrays of Windows are pointless as you need
|
||||
* to destruct them all at the same time too, which is kinda hard. */
|
||||
FORCEINLINE void *operator new[](size_t size) { NOT_REACHED(); }
|
||||
/* Don't free the window directly; it corrupts the linked list when iterating */
|
||||
FORCEINLINE void operator delete(void *ptr, size_t size) {}
|
||||
|
||||
uint16 flags4; ///< Window flags, @see WindowFlags
|
||||
WindowClass window_class; ///< Window class
|
||||
@ -543,8 +548,10 @@ extern Window *_z_front_window;
|
||||
extern Window *_z_back_window;
|
||||
|
||||
/** Iterate over all windows */
|
||||
#define FOR_ALL_WINDOWS_FROM_BACK(w) for (w = _z_back_window; w != NULL; w = w->z_front)
|
||||
#define FOR_ALL_WINDOWS_FROM_FRONT(w) for (w = _z_front_window; w != NULL; w = w->z_back)
|
||||
#define FOR_ALL_WINDOWS_FROM_BACK_FROM(w, start) for (w = start; w != NULL; w = w->z_front) if (w->window_class != WC_INVALID)
|
||||
#define FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, start) for (w = start; w != NULL; w = w->z_back) if (w->window_class != WC_INVALID)
|
||||
#define FOR_ALL_WINDOWS_FROM_BACK(w) FOR_ALL_WINDOWS_FROM_BACK_FROM(w, _z_back_window)
|
||||
#define FOR_ALL_WINDOWS_FROM_FRONT(w) FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, _z_front_window)
|
||||
|
||||
/**
|
||||
* Disable scrolling of the main viewport when an input-window is active.
|
||||
|
Loading…
Reference in New Issue
Block a user