[cairo-commit] 2 commits - src/cairo-image-surface.c test/cairo-test.c test/large-source.c test/large-source-roi.c test/large-source-roi.ref.png

M. Joonas Pihlaja joonas at kemper.freedesktop.org
Thu Sep 3 09:28:45 PDT 2009


 src/cairo-image-surface.c     |   27 +++++++++++++++++++++++++--
 test/cairo-test.c             |   14 +++++++-------
 test/large-source-roi.c       |    4 ++--
 test/large-source-roi.ref.png |binary
 test/large-source.c           |    4 ++--
 5 files changed, 36 insertions(+), 13 deletions(-)

New commits:
commit 9e45673e197d0f43e296483cc6b5ca6df94e7f02
Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
Date:   Thu Sep 3 19:18:07 2009 +0300

    [image] Check for out of bounds image surface sizes in constructors.
    
    The image surface code doesn't reliably work on images larger than
    32767 in width or height.  This patch makes the image surface
    constructors fail by returning a surface in the CAIRO_STATUS_INVALID_SIZE
    state when given negative or too large dimensions so that client code
    gets a prompt and correct error rather than flaky rendering on large
    images.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 1d778cd..b35905f 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -40,6 +40,18 @@
 #include "cairo-clip-private.h"
 #include "cairo-region-private.h"
 
+/* Limit on the width / height of an image surface in pixels.  This is
+ * mainly determined by coordinates of things sent to pixman at the
+ * moment being in 16.16 format. */
+#define MAX_IMAGE_SIZE 32767
+
+static cairo_bool_t
+_cairo_image_surface_is_size_valid (int width, int height)
+{
+    return 0 <= width  &&  width <= MAX_IMAGE_SIZE &&
+	   0 <= height && height <= MAX_IMAGE_SIZE;
+}
+
 static cairo_format_t
 _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
 {
@@ -152,6 +164,12 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
 					      pixman_format_code_t	 pixman_format)
 {
     cairo_image_surface_t *surface;
+    int width = pixman_image_get_width (pixman_image);
+    int height = pixman_image_get_height (pixman_image);
+
+    if (! _cairo_image_surface_is_size_valid (width, height)) {
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
+    }
 
     surface = malloc (sizeof (cairo_image_surface_t));
     if (unlikely (surface == NULL))
@@ -168,8 +186,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
     surface->owns_data = FALSE;
     surface->transparency = CAIRO_IMAGE_UNKNOWN;
 
-    surface->width = pixman_image_get_width (pixman_image);
-    surface->height = pixman_image_get_height (pixman_image);
+    surface->width = width;
+    surface->height = height;
     surface->stride = pixman_image_get_stride (pixman_image);
     surface->depth = pixman_image_get_depth (pixman_image);
     surface->is_clear = FALSE;
@@ -349,6 +367,11 @@ _cairo_image_surface_create_with_pixman_format (unsigned char		*data,
     cairo_surface_t *surface;
     pixman_image_t *pixman_image;
 
+    if (! _cairo_image_surface_is_size_valid (width, height))
+    {
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
+    }
+
     pixman_image = pixman_image_create_bits (pixman_format, width, height,
 					     (uint32_t *) data, stride);
 
diff --git a/test/large-source-roi.c b/test/large-source-roi.c
index 8709e4b..e429f98 100644
--- a/test/large-source-roi.c
+++ b/test/large-source-roi.c
@@ -47,7 +47,7 @@ static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
     cairo_surface_t *source;
-    double source_width = 66000.0;
+    double source_width = 32767.0;
 
     cairo_set_source_rgb (cr, 1,1,1);
     cairo_paint (cr);
@@ -72,5 +72,5 @@ CAIRO_TEST (large_source_roi,
 	    "Uses a all of a large source image.",
 	    "stress, source", /* keywords */
 	    NULL, /* requirements */
-	    20, 20,
+	    7, 7,
 	    NULL, draw)
diff --git a/test/large-source-roi.ref.png b/test/large-source-roi.ref.png
new file mode 100644
index 0000000..b8dc8b1
Binary files /dev/null and b/test/large-source-roi.ref.png differ
diff --git a/test/large-source.c b/test/large-source.c
index 5b2254c..b02b493 100644
--- a/test/large-source.c
+++ b/test/large-source.c
@@ -49,7 +49,7 @@ draw (cairo_t *cr, int width, int height)
     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
     cairo_paint (cr);
 
-    surface = cairo_image_surface_create (CAIRO_FORMAT_A1, 64000, 20);
+    surface = cairo_image_surface_create (CAIRO_FORMAT_A1, 32000, 20);
     data = cairo_image_surface_get_data (surface);
     if (data != NULL) {
 	int stride = cairo_image_surface_get_stride (surface);
@@ -68,7 +68,7 @@ draw (cairo_t *cr, int width, int height)
     cairo_mask_surface (cr, surface, 0, 0);
     cairo_surface_destroy (surface);
 
-    surface = cairo_image_surface_create (CAIRO_FORMAT_A1, 20, 64000);
+    surface = cairo_image_surface_create (CAIRO_FORMAT_A1, 20, 32000);
     data = cairo_image_surface_get_data (surface);
     if (data != NULL) {
 	int stride = cairo_image_surface_get_stride (surface);
commit 12d0613210547b8a50dd7b21a12eb1485ee496b9
Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
Date:   Thu Sep 3 17:54:49 2009 +0300

    [test] Allow tests to XFAIL by putting the cairo_t into an error state.
    
    The test runner was extra strict about never letting a test put
    the cairo_t into an error state, and never would it check for
    the expectedness status of the failure.  This patch moves the
    check for a test being an XFAIL above the check on the cairo_t's
    final status.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 7e93410..55e28dc 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1005,13 +1005,6 @@ REPEAT:
 	goto UNWIND_CAIRO;
     }
 
-    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
-	cairo_test_log (ctx, "Error: Function under test left cairo status in an error state: %s\n",
-			cairo_status_to_string (cairo_status (cr)));
-	ret = CAIRO_TEST_FAILURE;
-	goto UNWIND_CAIRO;
-    }
-
 #if HAVE_MEMFAULT
     if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
 	MEMFAULT_HAS_FAULTS ())
@@ -1380,6 +1373,13 @@ REPEAT:
 	cairo_surface_destroy (diff_image);
     }
 
+    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
+	cairo_test_log (ctx, "Error: Function under test left cairo status in an error state: %s\n",
+			cairo_status_to_string (cairo_status (cr)));
+	ret = CAIRO_TEST_FAILURE;
+	goto UNWIND_CAIRO;
+    }
+
 UNWIND_CAIRO:
     if (test_filename != NULL) {
 	free (test_filename);


More information about the cairo-commit mailing list