[PATCH] egl: refcount wl_egl_window objects. fix memory corruption
Giulio Camuffo
giuliocamuffo at gmail.com
Mon Oct 7 22:09:17 CEST 2013
Suppose we create a wl_egl_window and an EGLSurface. Then we call
eglMakeCurrent(dpy,surf,surf,ctx) with that surface, render and swap.
Later we destroy the surface and the window, and we make current
another surface. That resulted in two invalid writes because
the surface, which is refcounted, gets actually deleted at the
eglMakeCurrent() call, and in dri2_destroy_surface() its window
was used, window which was deleted earlier.
So make also wl_egl_window refcounted, so that it isn't destroyed
while its surface is still alive.
Cc: mesa-stable at lists.freedesktop.org
---
src/egl/drivers/dri2/platform_wayland.c | 3 +++
src/egl/wayland/wayland-egl/wayland-egl-priv.h | 2 ++
src/egl/wayland/wayland-egl/wayland-egl.c | 5 ++++-
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 1d417bb..831cd23 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -143,6 +143,7 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
dri2_surf->wl_win->private = dri2_surf;
dri2_surf->wl_win->resize_callback = resize_callback;
+ ++dri2_surf->wl_win->ref_count;
dri2_surf->base.Width = -1;
dri2_surf->base.Height = -1;
@@ -222,6 +223,8 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
dri2_surf->wl_win->resize_callback = NULL;
}
+ (dri2_surf->wl_win->destroy)(dri2_surf->wl_win);
+
free(surf);
return EGL_TRUE;
diff --git a/src/egl/wayland/wayland-egl/wayland-egl-priv.h b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
index da25be9..302e2cf 100644
--- a/src/egl/wayland/wayland-egl/wayland-egl-priv.h
+++ b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
@@ -25,8 +25,10 @@ struct wl_egl_window {
int attached_width;
int attached_height;
+ int ref_count;
void *private;
void (*resize_callback)(struct wl_egl_window *, void *);
+ void (*destroy)(struct wl_egl_window *);
};
#ifdef __cplusplus
diff --git a/src/egl/wayland/wayland-egl/wayland-egl.c b/src/egl/wayland/wayland-egl/wayland-egl.c
index 8bd49cf..7a93987 100644
--- a/src/egl/wayland/wayland-egl/wayland-egl.c
+++ b/src/egl/wayland/wayland-egl/wayland-egl.c
@@ -34,6 +34,8 @@ wl_egl_window_create(struct wl_surface *surface,
wl_egl_window_resize(egl_window, width, height, 0, 0);
egl_window->attached_width = 0;
egl_window->attached_height = 0;
+ egl_window->ref_count = 1;
+ egl_window->destroy = wl_egl_window_destroy;
return egl_window;
}
@@ -41,7 +43,8 @@ wl_egl_window_create(struct wl_surface *surface,
WL_EGL_EXPORT void
wl_egl_window_destroy(struct wl_egl_window *egl_window)
{
- free(egl_window);
+ if (--egl_window->ref_count < 1)
+ free(egl_window);
}
WL_EGL_EXPORT void
--
1.8.4
More information about the wayland-devel
mailing list