diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-02 08:47:26 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-02 08:55:37 +0000 |
commit | 18cff63e3d288bf2d7773760f2ab25c80a4a2bc1 (patch) | |
tree | 069c8f0a069521ecb9ad13746ff3ac93c3435981 | |
parent | c391093f40472c2300f38d0e5857858f85586b60 (diff) |
surface: Prevent writes to the user-data arrays during teardown
As we cleanup the user-data arrays, we call the user provided destroy
notifier callbacks. These callbacks are at liberty to write back into
the parent surface, and in particular try to write into the arrays that
we have just freed. This causes hard to control and fairly unpredictable
use-after-frees in the client, so lets just rule out the dangerous
behaviour.
References:https://bugzilla.mozilla.org/show_bug.cgi?id=722975
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/cairo-surface.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/src/cairo-surface.c b/src/cairo-surface.c index ffffef86b..5ec659e01 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -1126,6 +1126,9 @@ cairo_surface_set_user_data (cairo_surface_t *surface, if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) return surface->status; + if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)) + return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); + return _cairo_user_data_array_set_data (&surface->user_data, key, user_data, destroy); } @@ -1276,6 +1279,12 @@ cairo_surface_set_mime_data (cairo_surface_t *surface, cairo_status_t status; cairo_mime_data_t *mime_data; + if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) + return surface->status; + + if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)) + return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); + if (unlikely (surface->status)) return surface->status; if (unlikely (surface->finished)) |