diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 1d778cdb7..b35905f5f 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 8709e4b47..e429f989c 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 000000000..b8dc8b1b6 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 5b2254cc2..b02b493a5 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);