[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.
This commit is contained in:
Chris Wilson 2007-10-03 23:19:10 +01:00
parent 8cba73a36c
commit e49bcde27f
9 changed files with 46 additions and 13 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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().
@ -75,13 +75,35 @@
((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \
_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().
*

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {