summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-08-23 12:48:08 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-08-23 12:53:27 +0100
commitfb8881e84bb24b2a54ee5aa449b6f5638de36404 (patch)
treeb0c7f183f19ece1a8ad0ff2c45934ce21417cb04
parent054f34111d220541bc785b30207387541fdd31d2 (diff)
win32: Prevent double-free of similar images
Based on a patch and analysis by Michael Henning. When we create a similar-image surface for win32, we set up a couple of back references from the image to the win32 surface, and vice versa. We need to be careful when decoupling the reference cycle to avoid chasing around the loop upon destruction. Currently we handled destroying the similar-image via the parent win32 surface, but similar precaution is required when destroying the surface via the similar-image. Reported-by: Michael Henning <drawoc@darkrefraction.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=63787 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/cairo-image-surface.c3
-rw-r--r--src/win32/cairo-win32-display-surface.c3
2 files changed, 4 insertions, 2 deletions
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 5390d4a37..824dbf3c6 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -848,8 +848,9 @@ _cairo_image_surface_finish (void *abstract_surface)
}
if (surface->parent) {
- cairo_surface_destroy (surface->parent);
+ cairo_surface_t *parent = surface->parent;
surface->parent = NULL;
+ cairo_surface_destroy (parent);
}
return CAIRO_STATUS_SUCCESS;
diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c
index 039062520..5ecdbee3e 100644
--- a/src/win32/cairo-win32-display-surface.c
+++ b/src/win32/cairo-win32-display-surface.c
@@ -415,7 +415,8 @@ _cairo_win32_display_surface_finish (void *abstract_surface)
{
cairo_win32_display_surface_t *surface = abstract_surface;
- if (surface->image) {
+ if (surface->image && to_image_surface(surface->image)->parent) {
+ assert (to_image_surface(surface->image)->parent == &surface->win32.base);
/* Unhook ourselves first to avoid the double-unref from the image */
to_image_surface(surface->image)->parent = NULL;
cairo_surface_finish (surface->image);