diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-23 12:48:08 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-23 12:53:27 +0100 |
commit | fb8881e84bb24b2a54ee5aa449b6f5638de36404 (patch) | |
tree | b0c7f183f19ece1a8ad0ff2c45934ce21417cb04 | |
parent | 054f34111d220541bc785b30207387541fdd31d2 (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.c | 3 | ||||
-rw-r--r-- | src/win32/cairo-win32-display-surface.c | 3 |
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); |