[cairo-commit] src/cairo-glitz-surface.c src/cairo-gstate.c src/cairoint.h src/cairo-meta-surface.c src/cairo-pattern.c src/cairo-quartz-surface.c src/cairo-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Wed May 9 02:23:14 PDT 2007


 src/cairo-glitz-surface.c  |   12 +++++++--
 src/cairo-gstate.c         |   55 +++++++++++++++++++++++++++++++--------------
 src/cairo-meta-surface.c   |    6 ++++
 src/cairo-pattern.c        |   30 ++++++++++++++++++------
 src/cairo-quartz-surface.c |    6 ++++
 src/cairo-surface.c        |   47 +++++++++++++++++++++++++++-----------
 src/cairoint.h             |    2 -
 7 files changed, 113 insertions(+), 45 deletions(-)

New commits:
diff-tree 8ddfc1b2e4aeefb704e05e64661b5c9985788e99 (from dbdaf0690e1121d0f810dfb035e7a9f0dae17248)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue May 8 16:13:08 2007 +0100

    [cairo-pattern] Return status from _cairo_pattern_init_copy()
    
    During the copy, allocation of the gradient may fail and so the callers
    need to check for a pattern that returned in an error state. No callers
    did so and in order to force all callers to check the error status,
    the status return was added to _cairo_pattern_init_copy().  The early
    error checking may appear redundant for an object with an embedded
    structure, however it does fix an error where an uninitialised pattern
    was being used:
    
    ==1922== Process terminating with default action of signal 11 (SIGSEGV)
    ==1922==  Access not within mapped region at address 0x55555555
    ==1922==    at 0x402CF6F: _cairo_array_index (cairo-array.c:208)
    ==1922==    by 0x402D4F3: _cairo_user_data_array_fini (cairo-array.c:370)
    ==1922==    by 0x4046464: _cairo_pattern_fini (cairo-pattern.c:188)
    ==1922==    by 0x404992A: _cairo_meta_surface_paint (cairo-meta-surface.c:266)
    ==1922==    by 0x403FCE0: _cairo_surface_paint (cairo-surface.c:1331)
    ==1922==    by 0x405CB5E: _test_meta_surface_paint (test-meta-surface.c:195)
    ==1922==    by 0x403FCE0: _cairo_surface_paint (cairo-surface.c:1331)
    ==1922==    by 0x4032A60: _cairo_gstate_paint (cairo-gstate.c:822)
    ==1922==    by 0x402B2D1: cairo_paint (cairo.c:1879)
    ==1922==    by 0x804A4F7: draw (radial-gradient.c:73)
    ==1922==    by 0x804AFA4: cairo_test_expecting (cairo-test.c:326)
    ==1922==    by 0x804A57C: main (radial-gradient.c:109)
    ==1922== Injected fault at:
    ==1922==    at 0x4020EA5: malloc (vg_replace_malloc.c:207)
    ==1922==    by 0x404475C: _cairo_pattern_init_copy (cairo-pattern.c:136)
    ==1922==    by 0x403F779: _cairo_surface_copy_pattern_for_destination (cairo-surface.c:2153)
    ==1922==    by 0x403FCC1: _cairo_surface_paint (cairo-surface.c:1328)
    ==1922==    by 0x405CB5E: _test_meta_surface_paint (test-meta-surface.c:195)
    ==1922==    by 0x403FCE0: _cairo_surface_paint (cairo-surface.c:1331)
    ==1922==    by 0x4032A60: _cairo_gstate_paint (cairo-gstate.c:822)
    ==1922==    by 0x402B2D1: cairo_paint (cairo.c:1879)
    ==1922==    by 0x804A4F7: draw (radial-gradient.c:73)
    ==1922==    by 0x804AFA4: cairo_test_expecting (cairo-test.c:326)
    ==1922==    by 0x804A57C: main (radial-gradient.c:109)

diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 031c081..ab15404 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -829,7 +829,9 @@ _cairo_glitz_pattern_acquire_surfaces (c
 
 	mask = NULL;
     } else {
-	_cairo_pattern_init_copy (&tmp.base, src);
+	status = _cairo_pattern_init_copy (&tmp.base, src);
+	if (status)
+	    return status;
     }
 
     status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
@@ -844,7 +846,9 @@ _cairo_glitz_pattern_acquire_surfaces (c
 
     if (mask)
     {
-	_cairo_pattern_init_copy (&tmp.base, mask);
+	status = _cairo_pattern_init_copy (&tmp.base, mask);
+	if (status)
+	    return status;
 
 	status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
 						       mask_x, mask_y,
@@ -1075,7 +1079,9 @@ _cairo_glitz_surface_composite_trapezoid
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
     {
-	_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
+	status = _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
+	if (status)
+	    return status;
 
 	status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base,
 						       dst,
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 0a77df4..3787aeb 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -764,7 +764,7 @@ _cairo_gstate_stroke_to_path (cairo_gsta
 }
 */
 
-static void
+static cairo_status_t
 _cairo_gstate_copy_transformed_pattern (cairo_gstate_t  *gstate,
 					cairo_pattern_t *pattern,
 					cairo_pattern_t *original,
@@ -772,8 +772,12 @@ _cairo_gstate_copy_transformed_pattern (
 {
     cairo_surface_pattern_t *surface_pattern;
     cairo_surface_t *surface;
+    cairo_status_t status;
+
+    status = _cairo_pattern_init_copy (pattern, original);
+    if (status)
+	return status;
 
-    _cairo_pattern_init_copy (pattern, original);
     _cairo_pattern_transform (pattern, ctm_inverse);
 
     if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) {
@@ -783,25 +787,26 @@ _cairo_gstate_copy_transformed_pattern (
             _cairo_pattern_transform (pattern, &surface->device_transform);
     }
 
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 _cairo_gstate_copy_transformed_source (cairo_gstate_t  *gstate,
 				       cairo_pattern_t *pattern)
 {
-    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
-					    gstate->source,
-					    &gstate->source_ctm_inverse);
+    return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+					           gstate->source,
+					           &gstate->source_ctm_inverse);
 }
 
-static void
+static cairo_status_t
 _cairo_gstate_copy_transformed_mask (cairo_gstate_t  *gstate,
 				     cairo_pattern_t *pattern,
 				     cairo_pattern_t *mask)
 {
-    _cairo_gstate_copy_transformed_pattern (gstate, pattern,
-					    mask,
-					    &gstate->ctm_inverse);
+    return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+					           mask,
+					           &gstate->ctm_inverse);
 }
 
 cairo_status_t
@@ -817,7 +822,9 @@ _cairo_gstate_paint (cairo_gstate_t *gst
     if (status)
 	return status;
 
-    _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+    status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+    if (status)
+	return status;
 
     status = _cairo_surface_paint (gstate->target,
 				   gstate->op,
@@ -924,16 +931,22 @@ _cairo_gstate_mask (cairo_gstate_t  *gst
     if (status)
 	return status;
 
-    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
-    _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
+    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    if (status)
+	return status;
+
+    status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
+    if (status)
+	goto CLEANUP_SOURCE;
 
     status = _cairo_surface_mask (gstate->target,
 				  gstate->op,
 				  &source_pattern.base,
 				  &mask_pattern.base);
 
-    _cairo_pattern_fini (&source_pattern.base);
     _cairo_pattern_fini (&mask_pattern.base);
+CLEANUP_SOURCE:
+    _cairo_pattern_fini (&source_pattern.base);
 
     return status;
 }
@@ -954,7 +967,10 @@ _cairo_gstate_stroke (cairo_gstate_t *gs
     if (status)
 	return status;
 
-    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    status = _cairo_gstate_copy_transformed_source (gstate,
+	                                            &source_pattern.base);
+    if (status)
+	return status;
 
     status = _cairo_surface_stroke (gstate->target,
 				    gstate->op,
@@ -1021,7 +1037,9 @@ _cairo_gstate_fill (cairo_gstate_t *gsta
     if (status)
 	return status;
 
-    _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+    status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+    if (status)
+	return status;
 
     status = _cairo_surface_fill (gstate->target,
 				  gstate->op,
@@ -1561,7 +1579,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_
     _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
                                                transformed_glyphs);
 
-    _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+    if (status)
+	goto CLEANUP_GLYPHS;
 
     status = _cairo_surface_show_glyphs (gstate->target,
 					 gstate->op,
@@ -1572,6 +1592,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_
 
     _cairo_pattern_fini (&source_pattern.base);
 
+CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
       free (transformed_glyphs);
 
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 56c702c..98ccaaf 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -212,7 +212,11 @@ static cairo_status_t
 _init_pattern_with_snapshot (cairo_pattern_t       *pattern,
 			     const cairo_pattern_t *other)
 {
-    _cairo_pattern_init_copy (pattern, other);
+    cairo_status_t status;
+
+    status = _cairo_pattern_init_copy (pattern, other);
+    if (status)
+	return status;
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	cairo_surface_pattern_t *surface_pattern =
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 3c2382c..033519c 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -110,7 +110,7 @@ _cairo_pattern_init (cairo_pattern_t *pa
     cairo_matrix_init_identity (&pattern->matrix);
 }
 
-static void
+static cairo_status_t
 _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t	  *pattern,
 				   const cairo_gradient_pattern_t *other)
 {
@@ -139,21 +139,23 @@ _cairo_gradient_pattern_init_copy (cairo
 	    pattern->stops_size = 0;
 	    pattern->n_stops = 0;
 	    _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
-	    return;
+	    return CAIRO_STATUS_NO_MEMORY;
 	}
 
 	memcpy (pattern->stops, other->stops,
 		other->n_stops * sizeof (pixman_gradient_stop_t));
     }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-void
+cairo_status_t
 _cairo_pattern_init_copy (cairo_pattern_t	*pattern,
 			  const cairo_pattern_t *other)
 {
     if (other->status) {
 	_cairo_pattern_set_error (pattern, other->status);
-	return;
+	return other->status;
     }
 
     switch (other->type) {
@@ -174,12 +176,18 @@ _cairo_pattern_init_copy (cairo_pattern_
     case CAIRO_PATTERN_TYPE_RADIAL: {
 	cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
 	cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
+	cairo_status_t status;
+
+	status = _cairo_gradient_pattern_init_copy (dst, src);
+	if (status)
+	    return status;
 
-	_cairo_gradient_pattern_init_copy (dst, src);
     } break;
     }
 
     pattern->ref_count = 1;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 void
@@ -1812,7 +1820,9 @@ _cairo_pattern_acquire_surfaces (cairo_p
     }
     else
     {
-	_cairo_pattern_init_copy (&src_tmp.base, src);
+	status = _cairo_pattern_init_copy (&src_tmp.base, src);
+	if (status)
+	    return status;
     }
 
     status = _cairo_pattern_acquire_surface (&src_tmp.base, dst,
@@ -1831,19 +1841,23 @@ _cairo_pattern_acquire_surfaces (cairo_p
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    _cairo_pattern_init_copy (&mask_tmp.base, mask);
+    status = _cairo_pattern_init_copy (&mask_tmp.base, mask);
+    if (status)
+	goto CLEANUP_SOURCE;
 
     status = _cairo_pattern_acquire_surface (&mask_tmp.base, dst,
 					     mask_x, mask_y,
 					     width, height,
 					     mask_out, mask_attributes);
 
+    _cairo_pattern_fini (&mask_tmp.base);
+
+CLEANUP_SOURCE:
     if (status)
 	_cairo_pattern_release_surface (&src_tmp.base,
 					*src_out, src_attributes);
 
     _cairo_pattern_fini (&src_tmp.base);
-    _cairo_pattern_fini (&mask_tmp.base);
 
     return status;
 }
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 5469e40..0c4414b 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -515,7 +515,11 @@ static cairo_status_t
 _init_pattern_with_snapshot (cairo_pattern_t *pattern,
 			     const cairo_pattern_t *other)
 {
-    _cairo_pattern_init_copy (pattern, other);
+    cairo_status_t status;
+
+    status = _cairo_pattern_init_copy (pattern, other);
+    if (status)
+	return status;
 
     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	cairo_surface_pattern_t *surface_pattern =
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 94bb405..680ff0c 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -80,7 +80,7 @@ DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT
 DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
 DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
 
-static void
+static cairo_status_t
 _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
 					     cairo_surface_t *destination,
 					     cairo_pattern_t *pattern_out);
@@ -1325,7 +1325,9 @@ _cairo_surface_paint (cairo_surface_t	*s
 
     assert (! surface->is_snapshot);
 
-    _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+    if (status)
+	return status;
 
     if (surface->backend->paint) {
 	status = surface->backend->paint (surface, op, &dev_source.base);
@@ -1353,20 +1355,26 @@ _cairo_surface_mask (cairo_surface_t	*su
 
     assert (! surface->is_snapshot);
 
-    _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
-    _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
+    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+    if (status)
+	goto FINISH;
+    status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
+    if (status)
+	goto CLEANUP_SOURCE;
 
     if (surface->backend->mask) {
 	status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-            goto FINISH;
+            goto CLEANUP_MASK;
     }
 
     status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base);
 
- FINISH:
+ CLEANUP_MASK:
     _cairo_pattern_fini (&dev_mask.base);
+ CLEANUP_SOURCE:
     _cairo_pattern_fini (&dev_source.base);
+ FINISH:
 
     return status;
 }
@@ -1391,7 +1399,9 @@ _cairo_surface_stroke (cairo_surface_t		
 
     assert (! surface->is_snapshot);
 
-    _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+    if (status)
+	return status;
 
     if (surface->backend->stroke) {
 	status = surface->backend->stroke (surface, op, &dev_source.base,
@@ -1430,7 +1440,9 @@ _cairo_surface_fill (cairo_surface_t	*su
 
     assert (! surface->is_snapshot);
 
-    _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+    status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
+    if (status)
+	return status;
 
     if (surface->backend->fill) {
 	status = surface->backend->fill (surface, op, &dev_source.base,
@@ -1830,9 +1842,11 @@ _cairo_surface_show_glyphs (cairo_surfac
     if (!num_glyphs)
 	return CAIRO_STATUS_SUCCESS;
 
-    _cairo_surface_copy_pattern_for_destination (source,
-						 surface,
-						 &dev_source.base);
+    status = _cairo_surface_copy_pattern_for_destination (source,
+						          surface,
+							  &dev_source.base);
+    if (status)
+	return status;
 
     cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
 
@@ -2145,16 +2159,19 @@ _cairo_surface_composite_shape_fixup_unb
  * Copies the given pattern, taking into account device scale and offsets
  * of the destination surface.
  */
-void
+static cairo_status_t
 _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
                                              cairo_surface_t *destination,
                                              cairo_pattern_t *pattern_out)
 {
-    _cairo_pattern_init_copy (pattern_out, pattern);
+    cairo_status_t status;
+
+    status = _cairo_pattern_init_copy (pattern_out, pattern);
+    if (status)
+	return status;
 
     if (_cairo_surface_has_device_transform (destination)) {
 	cairo_matrix_t device_to_surface = destination->device_transform;
-	cairo_status_t status;
 
 	status = cairo_matrix_invert (&device_to_surface);
 	/* We only ever allow for scaling (under the implementation's
@@ -2164,6 +2181,8 @@ _cairo_surface_copy_pattern_for_destinat
 
 	_cairo_pattern_transform (pattern_out, &device_to_surface);
     }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 /*  LocalWords:  rasterized
diff --git a/src/cairoint.h b/src/cairoint.h
index a5bbb63..7b0d57e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2254,7 +2254,7 @@ _cairo_slope_counter_clockwise (cairo_sl
 
 /* cairo_pattern.c */
 
-cairo_private void
+cairo_private cairo_status_t
 _cairo_pattern_init_copy (cairo_pattern_t	*pattern,
 			  const cairo_pattern_t *other);
 


More information about the cairo-commit mailing list