diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2007-10-03 23:19:10 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2007-10-04 00:42:29 +0100 |
commit | e49bcde27f88e21d5b8037a0089a226096f6514b (patch) | |
tree | 81093fdb6b2288c7338c73da2936812e3362489c | |
parent | 8cba73a36c4ec42601388bb9374f3182651bfe60 (diff) |
[malloc] Check for integer overflow when realloc'ing.
Perform similar sanity checks to Vlad's _cairo_malloc_ab() but on the
arguments to realloc instead.
-rw-r--r-- | src/cairo-array.c | 4 | ||||
-rw-r--r-- | src/cairo-lzw.c | 6 | ||||
-rw-r--r-- | src/cairo-malloc-private.h | 30 | ||||
-rw-r--r-- | src/cairo-path-stroke.c | 3 | ||||
-rw-r--r-- | src/cairo-pattern.c | 4 | ||||
-rw-r--r-- | src/cairo-pen.c | 3 | ||||
-rw-r--r-- | src/cairo-polygon.c | 3 | ||||
-rw-r--r-- | src/cairo-spline.c | 3 | ||||
-rw-r--r-- | src/cairo-traps.c | 3 |
9 files changed, 46 insertions, 13 deletions
diff --git a/src/cairo-array.c b/src/cairo-array.c index ff8cce40..3525c78d 100644 --- a/src/cairo-array.c +++ b/src/cairo-array.c @@ -138,8 +138,8 @@ _cairo_array_grow_by (cairo_array_t *array, int additional) } array->size = new_size; - new_elements = realloc (*array->elements, - array->size * array->element_size); + new_elements = _cairo_realloc_ab (*array->elements, + array->size, array->element_size); if (new_elements == NULL) { array->size = old_size; diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c index 370d258b..36a59fda 100644 --- a/src/cairo-lzw.c +++ b/src/cairo-lzw.c @@ -93,7 +93,11 @@ _lzw_buf_grow (lzw_buf_t *buf) if (buf->status) return buf->status; - new_data = realloc (buf->data, new_size); + new_data = NULL; + /* check for integer overflow */ + if (new_size / 2 == buf->data_size) + new_data = realloc (buf->data, new_size); + if (new_data == NULL) { free (buf->data); buf->data_size = 0; diff --git a/src/cairo-malloc-private.h b/src/cairo-malloc-private.h index ad22851b..f8094f91 100644 --- a/src/cairo-malloc-private.h +++ b/src/cairo-malloc-private.h @@ -59,7 +59,7 @@ * @n: number of elements to allocate * @size: size of each element * - * Allocates @a*@size memory using _cairo_malloc(), taking care to not + * Allocates @n*@size memory using _cairo_malloc(), taking care to not * overflow when doing the multiplication. Behaves much like * calloc(), except that the returned memory is not set to zero. * The memory should be freed using free(). @@ -76,12 +76,34 @@ _cairo_malloc((unsigned) (a) * (unsigned) (size))) /** + * _cairo_realloc_ab: + * @ptr: original pointer to block of memory to be resized + * @n: number of elements to allocate + * @size: size of each element + * + * Reallocates @ptr a block of @n*@size memory using realloc(), taking + * care to not overflow when doing the multiplication. The memory + * should be freed using free(). + * + * @size should be a constant so that the compiler can optimize + * out a constant division. + * + * Return value: A pointer to the newly allocated memory, or %NULL in + * case of realloc() failure or overflow (whereupon the original block + * of memory * is left untouched). + */ + +#define _cairo_realloc_ab(ptr, a, size) \ + ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \ + realloc(ptr, (unsigned) (a) * (unsigned) (size))) + +/** * _cairo_malloc_abc: - * @a: first factor of number of elements to allocate + * @n: first factor of number of elements to allocate * @b: second factor of number of elements to allocate * @size: size of each element * - * Allocates @a*@b*@size memory using _cairo_malloc(), taking care to not + * Allocates @n*@b*@size memory using _cairo_malloc(), taking care to not * overflow when doing the multiplication. Behaves like * _cairo_malloc_ab(). The memory should be freed using free(). * @@ -103,7 +125,7 @@ * @size: size of each element * @k: additional size to allocate * - * Allocates @a*@ksize+@k memory using _cairo_malloc(), taking care to not + * Allocates @n*@ksize+@k memory using _cairo_malloc(), taking care to not * overflow when doing the arithmetic. Behaves like * _cairo_malloc_ab(). The memory should be freed using free(). * diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index d8d989b0..70001977 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -1064,7 +1064,8 @@ _cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t *stroker, /* Common case is one rectangle of exactly 4 segments. */ if (new_size == 0) new_size = 4; - new_segments = realloc (stroker->segments, new_size * sizeof (cairo_line_t)); + new_segments = _cairo_realloc_ab (stroker->segments, + new_size, sizeof (cairo_line_t)); if (new_segments == NULL) return CAIRO_STATUS_NO_MEMORY; stroker->segments_size = new_size; diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 231f5b25..1830634e 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -765,7 +765,9 @@ _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern) if (new_stops) memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t)); } else { - new_stops = realloc (pattern->stops, new_size * sizeof (cairo_gradient_stop_t)); + new_stops = _cairo_realloc_ab (pattern->stops, + new_size, + sizeof (cairo_gradient_stop_t)); } if (new_stops == NULL) { diff --git a/src/cairo-pen.c b/src/cairo-pen.c index 8d5401db..471849b0 100644 --- a/src/cairo-pen.c +++ b/src/cairo-pen.c @@ -142,7 +142,8 @@ _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points) int i; num_vertices = pen->num_vertices + num_points; - vertices = realloc (pen->vertices, num_vertices * sizeof (cairo_pen_vertex_t)); + vertices = _cairo_realloc_ab (pen->vertices, + num_vertices, sizeof (cairo_pen_vertex_t)); if (vertices == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return CAIRO_STATUS_NO_MEMORY; diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c index 7128e4b5..3aa0c4cd 100644 --- a/src/cairo-polygon.c +++ b/src/cairo-polygon.c @@ -97,7 +97,8 @@ _cairo_polygon_grow (cairo_polygon_t *polygon) if (new_edges) memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t)); } else { - new_edges = realloc (polygon->edges, new_size * sizeof (cairo_edge_t)); + new_edges = _cairo_realloc_ab (polygon->edges, + new_size, sizeof (cairo_edge_t)); } if (new_edges == NULL) { diff --git a/src/cairo-spline.c b/src/cairo-spline.c index db748b30..70c4ede6 100644 --- a/src/cairo-spline.c +++ b/src/cairo-spline.c @@ -113,7 +113,8 @@ _cairo_spline_grow (cairo_spline_t *spline) if (new_points) memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t)); } else { - new_points = realloc (spline->points, new_size * sizeof (cairo_point_t)); + new_points = _cairo_realloc_ab (spline->points, + new_size, sizeof (cairo_point_t)); } if (new_points == NULL) { diff --git a/src/cairo-traps.c b/src/cairo-traps.c index 0a1ccbeb..8abd4ddc 100644 --- a/src/cairo-traps.c +++ b/src/cairo-traps.c @@ -265,7 +265,8 @@ _cairo_traps_grow (cairo_traps_t *traps) if (new_traps) memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded)); } else { - new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t)); + new_traps = _cairo_realloc_ab (traps->traps, + new_size, sizeof (cairo_trapezoid_t)); } if (new_traps == NULL) { |