mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-24 16:00:11 +01:00
[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.
This commit is contained in:
parent
12d0613210
commit
9e45673e19
4 changed files with 29 additions and 6 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
BIN
test/large-source-roi.ref.png
Normal file
BIN
test/large-source-roi.ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 112 B |
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue