summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2007-10-03 23:19:10 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2007-10-04 00:42:29 +0100
commite49bcde27f88e21d5b8037a0089a226096f6514b (patch)
tree81093fdb6b2288c7338c73da2936812e3362489c
parent8cba73a36c4ec42601388bb9374f3182651bfe60 (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.c4
-rw-r--r--src/cairo-lzw.c6
-rw-r--r--src/cairo-malloc-private.h30
-rw-r--r--src/cairo-path-stroke.c3
-rw-r--r--src/cairo-pattern.c4
-rw-r--r--src/cairo-pen.c3
-rw-r--r--src/cairo-polygon.c3
-rw-r--r--src/cairo-spline.c3
-rw-r--r--src/cairo-traps.c3
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) {