summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-08-23 11:48:08 (GMT)
committerChris Wilson <chris@chris-wilson.co.uk>2013-08-23 11:53:27 (GMT)
commitfb8881e84bb24b2a54ee5aa449b6f5638de36404 (patch)
treeb0c7f183f19ece1a8ad0ff2c45934ce21417cb04
parent054f34111d220541bc785b30207387541fdd31d2 (diff)
downloadcairo-fb8881e84bb24b2a54ee5aa449b6f5638de36404.tar.gz
cairo-fb8881e84bb24b2a54ee5aa449b6f5638de36404.tar.xz
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 5390d4a..824dbf3 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 0390625..5ecdbee 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);