[cairo-commit] 10 commits - boilerplate/cairo-boilerplate.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-scaled-font-subsets.c src/cairo-svg-surface.c src/cairo-truetype-subset.c src/cairo-type1-fallback.c test/cairo-test.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Mar 31 04:16:14 PDT 2009


 boilerplate/cairo-boilerplate.c |   16 +++++++++++++---
 src/cairo-pdf-surface.c         |   27 +++++++++++++++++----------
 src/cairo-ps-surface.c          |    5 +++++
 src/cairo-scaled-font-subsets.c |    6 +++++-
 src/cairo-svg-surface.c         |    2 ++
 src/cairo-truetype-subset.c     |   13 +++++++++----
 src/cairo-type1-fallback.c      |    6 +++---
 test/cairo-test.c               |   35 +++++++++++++++++++++++++++++++++++
 8 files changed, 89 insertions(+), 21 deletions(-)

New commits:
commit e46c1d7fa34b4ba89fc3e0fe6f3042a6fa8c0398
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 10:39:46 2009 +0100

    [scaled-font-subset] Cleanup after failure to convert to utf16.
    
    Avoid leaking the local hashtable and strings after failing to convert the
    string to utf16.

diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 1d16e4a..44e850e 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -1025,7 +1025,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
 	if (utf8 && *utf8) {
 	    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
 	    if (unlikely (status))
-		return status; /* FIXME */
+		goto CLEANUP_HASH;
 	}
 
 	if (utf16_len == 1) {
commit 180b964aac4e058e6783778d33772f08e13b3669
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 10:37:44 2009 +0100

    [scaled-font-subset] Propagate error from scaled-font to collection.
    
    Don't attempt to collect the sub_font if it is in error.

diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index c802c31..1d16e4a 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -542,6 +542,10 @@ _cairo_sub_font_collect (void *entry, void *closure)
     if (collection->status)
 	return;
 
+    collection->status = sub_font->scaled_font->status;
+    if (collection->status)
+	return;
+
     for (i = 0; i <= sub_font->current_subset; i++) {
 	collection->subset_id = i;
 	collection->num_glyphs = 0;
commit 8362c6f726979abc43ad9f7303bd45fcb03f83b3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 10:36:08 2009 +0100

    [type1] Fixup error path during write_charstrings()
    
    On the common error path we attempted to unlock a mutex that was not
    always held, so reorder the error paths appropriately.

diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index 2b6768d..1023bbd 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -449,14 +449,14 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t    *font,
         /* four "random" bytes required by encryption algorithm */
         status = _cairo_array_append_multiple (&data, zeros, 4);
         if (unlikely (status))
-            goto fail;
+	    break;
 
         status = cairo_type1_font_create_charstring (font, i,
 						     font->scaled_font_subset->glyphs[i],
                                                      CAIRO_CHARSTRING_TYPE1,
 						     &data);
         if (unlikely (status))
-            goto fail;
+	    break;
 
         charstring_encrypt (&data);
         length = _cairo_array_num_elements (&data);
@@ -474,9 +474,9 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t    *font,
                                     length);
         _cairo_output_stream_printf (encrypted_output, " ND\n");
     }
+    _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
 
 fail:
-    _cairo_scaled_font_thaw_cache (font->type1_scaled_font);
     _cairo_array_fini (&data);
     return status;
 }
commit 88956cd42e9cc03cb8b4ec730062993eaaf3938d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 10:35:24 2009 +0100

    [ps] Check for error during stroking.
    
    Add a missing error status check that caused errors during stroke to be
    masked.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index dfdc785..0037905 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3317,6 +3317,9 @@ _cairo_ps_surface_stroke (void			*abstract_surface,
     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
         return CAIRO_STATUS_SUCCESS;
 
+    if (unlikely (status))
+	return status;
+
     return _cairo_pdf_operators_stroke (&surface->pdf_operators,
 					path,
 					style,
commit 043352aa8d1e3aeacf3b877f45e1bc451a676e15
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 10:34:41 2009 +0100

    [pdf] Prevent leak of pad_image on error path.
    
    Ensure that the local pad_image is destroyed after an error.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 04be7e9..886dd6b 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1797,7 +1797,7 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
 
     status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
     if (unlikely (status))
-	goto BAIL;
+	return status;
 
     pad_image = &image->base;
     if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD) {
@@ -1847,10 +1847,10 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
     *origin_x = x;
     *origin_y = y;
 
+BAIL:
     if (pad_image != &image->base)
 	cairo_surface_destroy (pad_image);
 
-BAIL:
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
     return status;
commit b0689f56118dd8ccda6f29901d41cf8f80983aa0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 31 10:27:15 2009 +0100

    Check for errors during get_mime_data()
    
    cairo_surface_get_mime_data() may raise an error on the surface, so we
    need to check lest it goes unnoticed and we generate a corrupt file.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 94da4ae..04be7e9 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1728,6 +1728,8 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
 				 &mime_data, &mime_data_length);
+    if (unlikely (source->status))
+	return source->status;
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 346bb88..dfdc785 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2138,6 +2138,8 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
 				 &mime_data, &mime_data_length);
+    if (unlikely (source->status))
+	return source->status;
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index db554a1..7a35fab 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1025,6 +1025,8 @@ _cairo_surface_base64_encode_png (cairo_surface_t       *surface,
 
     cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_PNG,
 				 &mime_data, &mime_data_length);
+    if (unlikely (surface->status))
+	return surface->status;
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
commit 9f63cbb870892253f363ddb7aac908263672c8dc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 30 19:09:13 2009 +0100

    [pdf] Free compressed stream after error.
    
    Ensure that the compressed stream is destroyed after encountering an
    error.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 2faa942..94da4ae 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1015,18 +1015,21 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,
 static cairo_status_t
 _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 {
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_status_t status;
     long length;
 
     if (! surface->pdf_stream.active)
 	return CAIRO_STATUS_SUCCESS;
 
     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
-    if (unlikely (status))
-	return status;
 
     if (surface->pdf_stream.compressed) {
-	status = _cairo_output_stream_destroy (surface->output);
+	cairo_status_t status2;
+
+	status2 = _cairo_output_stream_destroy (surface->output);
+	if (likely (status == CAIRO_STATUS_SUCCESS))
+	    status = status2;
+
 	surface->output = surface->pdf_stream.old_output;
 	_cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output);
 	surface->pdf_stream.old_output = NULL;
@@ -1051,7 +1054,7 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
 
     surface->pdf_stream.active = FALSE;
 
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (likely (status == CAIRO_STATUS_SUCCESS))
 	status = _cairo_output_stream_get_status (surface->output);
 
     return status;
commit ba1a0fa601a817ff489bc5373af57977e41eb99f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 30 19:08:41 2009 +0100

    [truetype] Free local names on failure.
    
    Ensure that all local allocations are freed on the error path.

diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 31e3971..8d1b597 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1329,8 +1329,8 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t  	 *scaled_font,
     tt_name_record_t *record;
     unsigned long size;
     int i, j;
-    char *ps_name;
-    char *font_name;
+    char *ps_name = NULL;
+    char *font_name = NULL;
 
     backend = scaled_font->backend;
     if (!backend->load_truetype_table)
@@ -1360,8 +1360,6 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t  	 *scaled_font,
      * name. It should be extended to use any suitable font name in
      * the name table.
      */
-    ps_name = NULL;
-    font_name = NULL;
     for (i = 0; i < be16_to_cpu(name->num_records); i++) {
         record = &(name->records[i]);
         if ((be16_to_cpu (record->platform) == 1) &&
@@ -1415,6 +1413,13 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t  	 *scaled_font,
 
 fail:
     free (name);
+
+    if (ps_name != NULL)
+	free (ps_name);
+
+    if (font_name != NULL)
+	free (font_name);
+
     *ps_name_out = NULL;
     *font_name_out = NULL;
 
commit edce97a750acf4368bd7249ec6b9a195f8584cdf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 30 16:50:51 2009 +0100

    [pdf] Remove false assertion.
    
    The stream itself may be in an error state, so an error could be raised.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index f562e3f..2faa942 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1324,10 +1324,12 @@ _cairo_pdf_surface_finish (void *abstract_surface)
 				 "%%%%EOF\n",
 				 offset);
 
-    status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
     /* pdf_operators has already been flushed when the last stream was
-     * closed so we should never be writing anything here. */
-    assert(status2 == CAIRO_STATUS_SUCCESS);
+     * closed so we should never be writing anything here - however,
+     * the stream may itself be in an error state. */
+    status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
+    if (status == CAIRO_STATUS_SUCCESS)
+	status = status2;
 
     /* close any active streams still open due to fatal errors */
     status2 = _cairo_pdf_surface_close_stream (surface);
commit b580a4a8d6c056ba8b47be32ea8c5b9a1d90d01e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 30 16:50:10 2009 +0100

    [test] Improve fault injection coverage
    
    In order to exercise the meta-surfaces, we need to inject faults into
    cairo_surface_finish().

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index b6c2c80..fcc05b8 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -76,6 +76,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <assert.h>
+#include <errno.h>
 
 #if HAVE_UNISTD_H && HAVE_FCNTL_H && HAVE_SIGNAL_H && HAVE_SYS_STAT_H && HAVE_SYS_SOCKET_H && HAVE_SYS_UN_H
 #include <unistd.h>
@@ -170,6 +171,9 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src,
     cairo_surface_t *surface;
     cairo_t *cr;
 
+    if (cairo_surface_status (src))
+	return cairo_surface_reference (src);
+
 #if 0
     if (cairo_surface_get_type (src) == CAIRO_SURFACE_TYPE_IMAGE) {
 	int ww = cairo_image_surface_get_width (src);
@@ -973,7 +977,7 @@ cairo_boilerplate_image_surface_create_from_ppm_stream (FILE *file)
 	goto FAIL;
     }
     if (cairo_surface_status (image))
-	goto FAIL;
+	return image;
 
     data = cairo_image_surface_get_data (image);
     stride = cairo_image_surface_get_stride (image);
@@ -1017,8 +1021,14 @@ cairo_boilerplate_convert_to_image (const char *filename, int page)
 
   RETRY:
     file = cairo_boilerplate_open_any2ppm (filename, page, flags);
-    if (file == NULL)
-	return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR);
+    if (file == NULL) {
+	switch (errno) {
+	case ENOMEM:
+	    return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+	default:
+	    return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR);
+	}
+    }
 
     image = cairo_boilerplate_image_surface_create_from_ppm_stream (file);
     ret = pclose (file);
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 264fed5..568d8f8 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -910,7 +910,42 @@ REPEAT:
 	cairo_status_t diff_status;
 
 	if (target->finish_surface != NULL) {
+#if HAVE_MEMFAULT
+	    /* We need to re-enable faults as most meta-surface processing
+	     * is done during cairo_surface_finish().
+	     */
+	    VALGRIND_CLEAR_FAULTS ();
+	    last_fault_count = VALGRIND_COUNT_FAULTS ();
+	    VALGRIND_ENABLE_FAULTS ();
+#endif
+
 	    diff_status = target->finish_surface (surface);
+
+#if HAVE_MEMFAULT
+	    VALGRIND_DISABLE_FAULTS ();
+
+	    if (ctx->malloc_failure &&
+		VALGRIND_COUNT_FAULTS () - last_fault_count > 0 &&
+		diff_status == CAIRO_STATUS_NO_MEMORY)
+	    {
+		cairo_destroy (cr);
+		cairo_surface_destroy (surface);
+		if (target->cleanup)
+		    target->cleanup (closure);
+		if (ctx->thread == 0) {
+		    cairo_debug_reset_static_data ();
+#if HAVE_FCFINI
+		    FcFini ();
+#endif
+		    if (VALGRIND_COUNT_LEAKS () > 0) {
+			VALGRIND_PRINT_FAULTS ();
+			VALGRIND_PRINT_LEAKS ();
+		    }
+		}
+
+		goto REPEAT;
+	    }
+#endif
 	    if (diff_status) {
 		cairo_test_log (ctx, "Error: Failed to finish surface: %s\n",
 				cairo_status_to_string (diff_status));


More information about the cairo-commit mailing list