[cairo-commit] CODING_STYLE pixman/src src/cairo-atsui-font.c src/cairo-bentley-ottmann.c src/cairo-beos-surface.cpp src/cairo-clip.c src/cairo-directfb-surface.c src/cairo-ft-font.c src/cairo-glitz-surface.c src/cairo-gstate.c src/cairo-hull.c src/cairoint.h src/cairo-malloc-private.h src/cairo-meta-surface.c src/cairo-os2-surface.c src/cairo-path.c src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-pen.c src/cairo-png.c src/cairo-polygon.c src/cairo-ps-surface.c src/cairo-quartz-surface.c src/cairo-scaled-font.c src/cairo-scaled-font-subsets.c src/cairo-spline.c src/cairo-stroke-style.c src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-svg-surface.c src/cairo-traps.c src/cairo-unicode.c src/cairo-win32-font.c src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-surface.c

Vladimir Vukicevic vladimir at kemper.freedesktop.org
Fri Jun 29 11:10:00 PDT 2007


 CODING_STYLE                    |   25 +++++++++
 pixman/src/fbcompose.c          |    4 -
 pixman/src/icimage.c            |    8 +--
 pixman/src/pixman.h             |    7 ++
 pixman/src/pixmanint.h          |   17 ++++++
 pixman/src/pixregion.c          |   59 ++++++++++++++++++----
 pixman/src/pixregionint.h       |    1 
 src/cairo-atsui-font.c          |    2 
 src/cairo-bentley-ottmann.c     |    6 +-
 src/cairo-beos-surface.cpp      |    4 -
 src/cairo-clip.c                |   10 ++-
 src/cairo-directfb-surface.c    |    2 
 src/cairo-ft-font.c             |    4 -
 src/cairo-glitz-surface.c       |   34 +++++++++++--
 src/cairo-gstate.c              |    6 +-
 src/cairo-hull.c                |    2 
 src/cairo-malloc-private.h      |  104 ++++++++++++++++++++++++++++++++++++++++
 src/cairo-meta-surface.c        |    4 -
 src/cairo-os2-surface.c         |    9 +--
 src/cairo-path.c                |    2 
 src/cairo-pattern.c             |    6 +-
 src/cairo-pdf-surface.c         |    6 +-
 src/cairo-pen.c                 |    4 -
 src/cairo-png.c                 |    6 +-
 src/cairo-polygon.c             |    2 
 src/cairo-ps-surface.c          |    4 -
 src/cairo-quartz-surface.c      |    8 +--
 src/cairo-scaled-font-subsets.c |    4 -
 src/cairo-scaled-font.c         |    2 
 src/cairo-spline.c              |    2 
 src/cairo-stroke-style.c        |    2 
 src/cairo-surface-fallback.c    |    4 -
 src/cairo-surface.c             |    2 
 src/cairo-svg-surface.c         |    2 
 src/cairo-traps.c               |    2 
 src/cairo-unicode.c             |    4 -
 src/cairo-win32-font.c          |    6 +-
 src/cairo-win32-surface.c       |    6 +-
 src/cairo-xcb-surface.c         |    8 +--
 src/cairo-xlib-surface.c        |    6 +-
 src/cairoint.h                  |    1 
 41 files changed, 308 insertions(+), 89 deletions(-)

New commits:
diff-tree 5c7d2d14d78e4dfb1ef6d2c40f0910f177e07360 (from fc34073464c487405b6e2e0a5fa269a1ae15a02a)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Jun 19 13:15:21 2007 -0700

    [fix] Avoid int overflow when allocating large buffers
    
    This patch introduces three macros: _cairo_malloc_ab,
    _cairo_malloc_abc, _cairo_malloc_ab_plus_c and replaces various calls
    to malloc(a*b), malloc(a*b*c), and malloc(a*b+c) with them.  The macros
    return NULL if int overflow would occur during the allocation.  See
    CODING_STYLE for more information.

diff --git a/CODING_STYLE b/CODING_STYLE
index 2aef41c..73fe2a9 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -243,3 +243,28 @@ The return statement is often the best t
 this. If it's not available due to additional nesting above which
 require some cleanup after the current block, then consider splitting
 the current block into a new function before using goto.
+
+Memory allocation
+-----------------
+
+Because much of cairo's data consists of dynamically allocated arrays,
+it's very easy to introduce integer overflow issues whenever malloc()
+is called.  Use the _cairo_malloc2(), _cairo_malloc3(), and
+_cairo_malloc2_add1 macros to avoid these cases; these macros check
+for overflow and will return NULL in that case.
+
+  malloc (n * size) => _cairo_malloc_ab (n, size)
+    e.g. malloc (num_elts * sizeof(some_type)) =>
+         _cairo_malloc2 (num_elts, sizeof(some_type))
+
+  malloc (a * b * size) => _cairo_malloc_abc (a, b, size)
+    e.g. malloc (width * height * 4) =>
+         _cairo_malloc3 (width, height, 4)
+
+  malloc (n * size + k) => _cairo_malloc_ab_plus_c (n, size, k)
+    e.g. malloc (num * sizeof(entry) + sizeof(header)) =>
+         _cairo_malloc2k (num, sizeof(entry), sizeof(header))
+
+In general, be wary of performing any arithmetic operations in an
+argument to malloc.  You should explicitly check for integer overflow
+yourself in any more complex situations.
\ No newline at end of file
diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c
index 4197e34..e2823ec 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -3883,7 +3883,7 @@ static void fbFetchExternalAlpha(Picture
     }
 
     if (width > SCANLINE_BUFFER_LENGTH)
-        alpha_buffer = (CARD32 *) malloc(width*sizeof(CARD32));
+        alpha_buffer = (CARD32 *) _pixman_malloc_ab (width, sizeof(CARD32));
 
     fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits);
     fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x,
@@ -4286,7 +4286,7 @@ pixman_compositeGeneral (pixman_operator
     compose_data.mask = pMask;
     compose_data.dest = pDst;
     if (width > SCANLINE_BUFFER_LENGTH)
-        scanline_buffer = (CARD32 *) malloc(width * 3 * sizeof(CARD32));
+	scanline_buffer = (CARD32 *) _pixman_malloc_abc (width, 3, sizeof(CARD32));
 
     n = pixman_region_num_rects (&region);
     pbox = pixman_region_rects (&region);
diff --git a/pixman/src/icimage.c b/pixman/src/icimage.c
index 61a84c5..8bcccc4 100644
--- a/pixman/src/icimage.c
+++ b/pixman/src/icimage.c
@@ -215,8 +215,8 @@ pixman_image_create_linear_gradient (con
     if (!image)
 	return NULL;
 
-    linear = malloc (sizeof (pixman_linear_gradient_image_t) +
-		     sizeof (pixman_gradient_stop_t) * n_stops);
+    linear = _pixman_malloc_ab_plus_c (n_stops, sizeof (pixman_gradient_stop_t),
+			       sizeof (pixman_linear_gradient_image_t));
     if (!linear)
     {
 	free (image);
@@ -259,8 +259,8 @@ pixman_image_create_radial_gradient (con
     if (!image)
 	return NULL;
 
-    radial = malloc (sizeof (pixman_radial_gradient_image_t) +
-		     sizeof (pixman_gradient_stop_t) * n_stops);
+    radial = _pixman_malloc_ab_plus_c (n_stops, sizeof (pixman_gradient_stop_t),
+			       sizeof (pixman_radial_gradient_image_t));
     if (!radial)
     {
 	free (image);
diff --git a/pixman/src/pixman.h b/pixman/src/pixman.h
index feaf60a..491fc89 100644
--- a/pixman/src/pixman.h
+++ b/pixman/src/pixman.h
@@ -89,6 +89,13 @@ SOFTWARE.
   typedef unsigned __int32 uint32_t;
   typedef __int64 int64_t;
   typedef unsigned __int64 uint64_t;
+
+# ifndef UINT16_MAX
+#  define UINT16_MAX	(65535)
+# endif
+# ifndef UINT32_MAX
+#  define UINT32_MAX	(0xffffffffU)
+# endif
 #else
 #error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
 #endif
diff --git a/pixman/src/pixmanint.h b/pixman/src/pixmanint.h
index a10a834..6ad373e 100644
--- a/pixman/src/pixmanint.h
+++ b/pixman/src/pixmanint.h
@@ -1073,4 +1073,21 @@ typedef	xFixed_16_16	xFixed;
 		       (*((a)+2) = (CARD8) ((v) >> 16))))
 #endif
 
+
+/* Allocation helpers */
+
+#define _pixman_malloc_ab(n, size) \
+  ((unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   malloc((unsigned) (n) * (unsigned) (size)))
+
+#define _pixman_malloc_abc(a, b, size) \
+  ((unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \
+   (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   malloc((unsigned) (a) * (unsigned) (b) * (unsigned) size))
+
+#define _pixman_malloc_ab_plus_c(n, size, k) \
+  ((unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   (unsigned) (k) >= INT32_MAX - (unsigned) (n) * (unsigned) (size) ? NULL : \
+   malloc((unsigned) (n) * (unsigned) (size) + (unsigned) (k)))
+
 #endif /* _PIXMANINT_H_ */
diff --git a/pixman/src/pixregion.c b/pixman/src/pixregion.c
index 4cd08e5..1ed3ad7 100644
--- a/pixman/src/pixregion.c
+++ b/pixman/src/pixregion.c
@@ -148,7 +148,31 @@ pixman_rect_alloc(pixman_region16_t * re
         ((r1)->y1 <= (r2)->y1) && \
         ((r1)->y2 >= (r2)->y2) )
 
-#define allocData(n) malloc(PIXREGION_SZOF(n))
+static size_t
+PIXREGION_SZOF(size_t n)
+{
+    size_t size = n * sizeof(pixman_box16_t);
+    if (n > UINT32_MAX / sizeof(pixman_box16_t))
+	return 0;
+
+    if (sizeof(pixman_region16_data_t) > UINT32_MAX - size)
+	return 0;
+
+    return size + sizeof(pixman_region16_data_t);
+}
+
+static void
+allocData(size_t n, void **data)
+{
+    size_t sz = PIXREGION_SZOF(n);
+    if (!sz) {
+	*data = NULL;
+	return;
+    }
+
+    *data = malloc(sz);
+}
+
 #define freeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
 
 #define RECTALLOC_BAIL(pReg,n,bail) \
@@ -185,7 +209,10 @@ if (!(pReg)->data || (((pReg)->data->num
 if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
 {									 \
     pixman_region16_data_t * NewData;							 \
-    NewData = (pixman_region16_data_t *)realloc((reg)->data, PIXREGION_SZOF(numRects));	 \
+    size_t data_size = PIXREGION_SZOF(numRects);			 \
+    if (!data_size)							 \
+      goto bail;							 \
+    NewData = (pixman_region16_data_t *)realloc((reg)->data, data_size); \
     if (NewData)							 \
     {									 \
 	NewData->size = (numRects);					 \
@@ -372,11 +399,12 @@ static pixman_region_status_t
 pixman_rect_alloc(pixman_region16_t * region, int n)
 {
     pixman_region16_data_t *data;
+    size_t data_size;
 
     if (!region->data)
     {
 	n++;
-	region->data = allocData(n);
+	allocData(n, (void **) &region->data);
 	if (!region->data)
 	    return pixman_break (region);
 	region->data->numRects = 1;
@@ -384,7 +412,7 @@ pixman_rect_alloc(pixman_region16_t * re
     }
     else if (!region->data->size)
     {
-	region->data = allocData(n);
+      allocData(n, (void **) &region->data);
 	if (!region->data)
 	    return pixman_break (region);
 	region->data->numRects = 0;
@@ -398,7 +426,10 @@ pixman_rect_alloc(pixman_region16_t * re
 		n = 250;
 	}
 	n += region->data->numRects;
-	data = (pixman_region16_data_t *)realloc(region->data, PIXREGION_SZOF(n));
+	data_size = PIXREGION_SZOF(n);
+	if (!data_size)
+	    return pixman_break (region);
+	data = (pixman_region16_data_t *)realloc(region->data, data_size);
 	if (!data)
 	    return pixman_break (region);
 	region->data = data;
@@ -424,7 +455,7 @@ pixman_region_copy(pixman_region16_t *ds
     if (!dst->data || (dst->data->size < src->data->numRects))
     {
 	freeData(dst);
-	dst->data = allocData(src->data->numRects);
+	allocData(src->data->numRects, (void **) &dst->data);
 	if (!dst->data)
 	    return pixman_break (dst);
 	dst->data->size = src->data->numRects;
@@ -835,8 +866,10 @@ pixman_op(
 	AppendRegions(newReg, r2BandEnd, r2End);
     }
 
-    if (oldData)
+    if (oldData) {
 	free(oldData);
+	oldData = NULL;
+    }
 
     if (!(numRects = newReg->data->numRects))
     {
@@ -1493,7 +1526,7 @@ pixman_region_validate(pixman_region16_t
 
     /* Set up the first region to be the first rectangle in badreg */
     /* Note that step 2 code will never overflow the ri[0].reg rects array */
-    ri = (RegionInfo *) malloc(4 * sizeof(RegionInfo));
+    ri = (RegionInfo *) _pixman_malloc_ab(4, sizeof(RegionInfo));
     if (!ri)
 	return pixman_break (badreg);
     sizeRI = 4;
@@ -1555,9 +1588,13 @@ pixman_region_validate(pixman_region16_t
 	/* Uh-oh.  No regions were appropriate.  Create a new one. */
 	if (sizeRI == numRI)
 	{
+	    size_t data_size;
 	    /* Oops, allocate space for new region information */
 	    sizeRI <<= 1;
-	    rit = (RegionInfo *) realloc(ri, sizeRI * sizeof(RegionInfo));
+	    data_size = sizeRI * sizeof(RegionInfo);
+	    if (data_size / sizeRI != sizeof(RegionInfo))
+		goto bail;
+	    rit = (RegionInfo *) realloc(ri, data_size);
 	    if (!rit)
 		goto bail;
 	    ri = rit;
@@ -1659,7 +1696,7 @@ pixman_region_rectsToRegion(nrects, prec
 	}
 	return region;
     }
-    pData = allocData(nrects);
+    allocData(nrects, &pData);
     if (!pData)
     {
 	pixman_break (region);
@@ -2167,7 +2204,7 @@ pixman_region16_data_copy(pixman_region1
     if (!dst->data || (dst->data->size < src->data->numRects))
     {
 	freeData(dst);
-	dst->data = allocData(src->data->numRects);
+	allocData(src->data->numRects, &dst->data);
 	if (!dst->data)
 	    return pixman_break (dst);
     }
diff --git a/pixman/src/pixregionint.h b/pixman/src/pixregionint.h
index 385a7f2..0ac7db4 100644
--- a/pixman/src/pixregionint.h
+++ b/pixman/src/pixregionint.h
@@ -70,6 +70,5 @@ typedef struct pixman_region16_point {
 #define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i])
 #define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects)
 #define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1)
-#define PIXREGION_SZOF(n) (sizeof(pixman_region16_data_t) + ((n) * sizeof(pixman_box16_t)))
 
 #endif /* _PIXREGIONINT_H_ */
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 361e787..d1196f0 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -809,7 +809,7 @@ _cairo_atsui_font_text_to_glyphs (void		
 
     *num_glyphs = glyphCount - 1;
     *glyphs =
-	(cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t)));
+	(cairo_glyph_t *) _cairo_malloc_ab(*num_glyphs, sizeof (cairo_glyph_t));
     if (*glyphs == NULL) {
 	return CAIRO_STATUS_NO_MEMORY;
     }
diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index b8d97fa..267459c 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -754,7 +754,7 @@ _cairo_bo_event_queue_init (cairo_bo_eve
      * or stop events, so this allocation is safe.  XXX: make the
      * event type a union so it doesn't always contain the skip
      * elt? */
-    events = malloc (num_events * (sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*)));
+    events = _cairo_malloc_ab (num_events, sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*));
     if (events == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
@@ -1436,7 +1436,7 @@ _cairo_bentley_ottmann_tessellate_polygo
     if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
 	edges = stack_edges;
     } else {
-	edges = malloc (polygon->num_edges * sizeof (cairo_bo_edge_t));
+	edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
 	if (edges == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
     }
@@ -1757,7 +1757,7 @@ run_test (const char		*test_name,
     while (intersections) {
 	int num_edges = _cairo_array_num_elements (&intersected_edges);
 	passes++;
-	edges = malloc (num_edges * sizeof (cairo_bo_edge_t));
+	edges = _cairo_malloc_ab (num_edges, sizeof (cairo_bo_edge_t));
 	assert (edges != NULL);
 	memcpy (edges, _cairo_array_index (&intersected_edges, 0), num_edges * sizeof (cairo_bo_edge_t));
 	_cairo_array_fini (&intersected_edges);
diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index abf094a..193fa43 100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
@@ -259,7 +259,7 @@ premultiply_rgba (unsigned char* data,
 		  int            height,
 		  int            stride)
 {
-    unsigned char* retdata = reinterpret_cast<unsigned char*>(malloc(stride * height));
+    unsigned char* retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
     if (!retdata)
 	return NULL;
 
@@ -322,7 +322,7 @@ _cairo_beos_bitmap_to_surface (BBitmap* 
 					bitmap->BytesPerRow());
     } else {
 	premultiplied = reinterpret_cast<unsigned char*>(
-					malloc(bitmap->BytesPerRow() * height));
+					_cairo_malloc_ab(bitmap->BytesPerRow(), height));
 	if (premultiplied)
 	    memcpy(premultiplied, bits, bitmap->BytesPerRow() * height);
     }
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 60f2418..8394077 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -634,9 +634,13 @@ _cairo_clip_copy_rectangle_list (cairo_c
         return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
 
     n_boxes = clip->has_region ? pixman_region_num_rects (&clip->region) : 1;
-    rectangles = malloc (sizeof (cairo_rectangle_t)*n_boxes);
-    if (rectangles == NULL)
-        return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
+    if (n_boxes > 0) {
+	rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t));
+	if (rectangles == NULL)
+	    return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
+    } else {
+	rectangles = NULL;
+    }
 
     if (clip->has_region) {
         pixman_box16_t *boxes;
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index fa31b06..5505501 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1113,7 +1113,7 @@ _cairo_directfb_surface_set_clip_region 
             if( surface->clips )
                 free (surface->clips);
             
-            surface->clips = malloc (n_boxes * sizeof(DFBRegion));
+            surface->clips = _cairo_malloc_ab (n_boxes, sizeof(DFBRegion));
             if (!surface->clips) {
                 surface->n_clips = 0;
                 return CAIRO_STATUS_NO_MEMORY;
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 89bb12a..4dc61ee 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -742,7 +742,7 @@ _get_bitmap_surface (FT_Bitmap		     *bi
 	    data = bitmap->buffer;
 	    assert (stride == bitmap->pitch);
 	} else {
-	    data = malloc (stride * height);
+	    data = _cairo_malloc_ab (height, stride);
 	    if (!data) {
 		_cairo_error (CAIRO_STATUS_NO_MEMORY);
 		return CAIRO_STATUS_NO_MEMORY;
@@ -792,7 +792,7 @@ _get_bitmap_surface (FT_Bitmap		     *bi
 	    if (own_buffer) {
 		data = bitmap->buffer;
 	    } else {
-		data = malloc (stride * height);
+		data = _cairo_malloc_ab (height, stride);
 		if (!data) {
 		    _cairo_error (CAIRO_STATUS_NO_MEMORY);
 		    return CAIRO_STATUS_NO_MEMORY;
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index ab15404..de91fc7 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -197,7 +197,7 @@ _cairo_glitz_surface_get_image (cairo_gl
     pf.bytes_per_line = (((width * format.bpp) / 8) + 3) & -4;
     pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
 
-    pixels = malloc (height * pf.bytes_per_line);
+    pixels = _cairo_malloc_ab (height, pf.bytes_per_line);
     if (!pixels)
 	return CAIRO_STATUS_NO_MEMORY;
 
@@ -627,8 +627,22 @@ _cairo_glitz_pattern_acquire_surface (ca
 
 	n_params = gradient->n_stops * 3 + n_base_params;
 
-	data = malloc (sizeof (glitz_fixed16_16_t) * n_params +
-		       sizeof (unsigned int) * gradient->n_stops);
+        /* check for int overflow */
+        {
+            int size1, size2;
+            if (n_params >= INT32_MAX / sizeof (glitz_fixed16_16_t) ||
+                gradient->n_stops >= INT32_MAX / sizeof (unsigned int))
+                return CAIRO_STATUS_NO_MEMORY;
+
+            size1 = n_params * sizeof (glitz_fixed16_16_t);
+            size2 = gradient->n_stops * sizeof (unsigned int);
+
+            if (size1 >= INT32_MAX - size2)
+                return CAIRO_STATUS_NO_MEMORY;
+
+            data = malloc (size1 + size2);
+        }
+
 	if (!data)
 	    return CAIRO_STATUS_NO_MEMORY;
 
@@ -1992,9 +2006,19 @@ _cairo_glitz_surface_old_show_glyphs (ca
     if (num_glyphs > N_STACK_BUF)
     {
 	char *data;
+        int size1, size2;
+
+        if (num_glyphs >= INT32_MAX / sizeof(void*) ||
+            num_glyphs >= INT32_MAX / sizeof(glitz_float_t) ||
+            (num_glyphs * sizeof(glitz_float_t)) >= INT32_MAX / 16)
+            goto FAIL1;
+
+        size1 = num_glyphs * sizeof(void *);
+        size2 = num_glyphs * sizeof(glitz_float_t) * 16;
+        if (size1 >= INT32_MAX - size2)
+            goto FAIL1;
 
-	data = malloc (num_glyphs * sizeof (void *) +
-		       num_glyphs * sizeof (glitz_float_t) * 16);
+	data = malloc (size1 + size2);
 	if (!data)
 	    goto FAIL1;
 
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index fc8c545..901fa58 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -530,7 +530,7 @@ _cairo_gstate_set_dash (cairo_gstate_t *
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    gstate->stroke_style.dash = malloc (gstate->stroke_style.num_dashes * sizeof (double));
+    gstate->stroke_style.dash = _cairo_malloc_ab (gstate->stroke_style.num_dashes, sizeof (double));
     if (gstate->stroke_style.dash == NULL) {
 	gstate->stroke_style.num_dashes = 0;
 	return CAIRO_STATUS_NO_MEMORY;
@@ -1570,7 +1570,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_
     if (num_glyphs <= STACK_GLYPHS_LEN) {
 	transformed_glyphs = stack_transformed_glyphs;
     } else {
-	transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
+	transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
 	if (transformed_glyphs == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
     }
@@ -1615,7 +1615,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t
     if (num_glyphs < STACK_GLYPHS_LEN)
       transformed_glyphs = stack_transformed_glyphs;
     else
-      transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
+      transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
     if (transformed_glyphs == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-hull.c b/src/cairo-hull.c
index e9d0a15..c56e9e0 100644
--- a/src/cairo-hull.c
+++ b/src/cairo-hull.c
@@ -62,7 +62,7 @@ _cairo_hull_create (cairo_pen_vertex_t *
     *extremum = vertices[0].point;
     vertices[0].point = tmp;
 
-    hull = malloc (num_vertices * sizeof (cairo_hull_t));
+    hull = _cairo_malloc_ab (num_vertices, sizeof (cairo_hull_t));
     if (hull == NULL)
 	return NULL;
 
diff --git a/src/cairo-malloc-private.h b/src/cairo-malloc-private.h
new file mode 100644
index 0000000..f503b39
--- /dev/null
+++ b/src/cairo-malloc-private.h
@@ -0,0 +1,104 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2007 Mozilla Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation
+ *
+ * Contributor(s):
+ *	Vladimir Vukicevic <vladimir at pobox.com>
+ */
+
+#ifndef CAIRO_MALLOC_PRIVATE_H
+#define CAIRO_MALLOC_PRIVATE_H
+
+#include "cairo-wideint-private.h"
+
+/**
+ * _cairo_malloc_ab:
+ * @n: number of elements to allocate
+ * @size: size of each element
+ *
+ * Allocates @a*@size memory using 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().
+ *
+ * @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 malloc() failure or overflow.
+ */
+
+#define _cairo_malloc_ab(a, size) \
+  ((unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   malloc((unsigned) (a) * (unsigned) (size)))
+
+/**
+ * _cairo_malloc_abc:
+ * @a: 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 malloc(), taking care to not
+ * overflow when doing the multiplication.  Behaves like
+ * _cairo_malloc_ab().  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 malloc() failure or overflow.
+ */
+
+#define _cairo_malloc_abc(a, b, size) \
+  ((unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \
+   (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   malloc((unsigned) (a) * (unsigned) (b) * (unsigned) size))
+
+/**
+ * _cairo_malloc_ab_plus_c:
+ * @n: number of elements to allocate
+ * @size: size of each element
+ * @k: additional size to allocate
+ *
+ * Allocates @a*@ksize+ at k memory using malloc(), taking care to not
+ * overflow when doing the arithmetic.  Behaves like
+ * _cairo_malloc_ab().  The memory should be freed using free().
+ *
+ * Return value: A pointer to the newly allocated memory, or %NULL in
+ * case of malloc() failure or overflow.
+ */
+
+#define _cairo_malloc_ab_plus_c(n, size, k) \
+  ((unsigned) (n) >= INT32_MAX / (unsigned) (size) ? NULL : \
+   (unsigned) (k) >= INT32_MAX - (unsigned) (n) * (unsigned) (size) ? NULL : \
+   malloc((unsigned) (n) * (unsigned) (size) + (unsigned) (k)))
+
+#endif /* CAIRO_MALLOC_PRIVATE_H */
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 8dbd608..30a64e7 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -439,7 +439,7 @@ _cairo_meta_surface_show_glyphs (void			
     if (status)
 	goto CLEANUP_COMMAND;
 
-    command->glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
+    command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
     if (command->glyphs == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto CLEANUP_SOURCE;
@@ -735,7 +735,7 @@ _cairo_meta_surface_replay (cairo_surfac
 	    int i, num_glyphs = command->show_glyphs.num_glyphs;
 
 	    if (has_device_transform) {
-		dev_glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
+		dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
 		if (dev_glyphs == NULL) {
 		    status = CAIRO_STATUS_NO_MEMORY;
 		    break;
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 319a7ab..1535de4 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -296,8 +296,9 @@ _cairo_os2_surface_blit_pixels (cairo_os
         ULONG ulPixels;
 
         /* allocate temporary pixel buffer */
-        pchPixBuf = (unsigned char *) malloc (3 * surface->bitmap_info.cx *
-                                              surface->bitmap_info.cy);
+        pchPixBuf = (unsigned char *) _cairo_malloc_abc (surface->bitmap_info.cy,
+						      surface->bitmap_info.cx,
+						      3);
         pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
         pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
 
@@ -713,7 +714,7 @@ cairo_os2_surface_create (HPS hps_client
     local_os2_surface->bitmap_info.cBitCount = 32;
 
     /* Allocate memory for pixels */
-    local_os2_surface->pixels = (unsigned char *) malloc (width * height * 4);
+    local_os2_surface->pixels = (unsigned char *) _cairo_malloc_abc (height, width, 4);
     if (!(local_os2_surface->pixels)) {
         /* Not enough memory for the pixels! */
         DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
@@ -783,7 +784,7 @@ cairo_os2_surface_set_size (cairo_surfac
     }
 
     /* Allocate memory for new stuffs */
-    pchNewPixels = (unsigned char *) malloc (new_width * new_height * 4);
+    pchNewPixels = (unsigned char *) _cairo_malloc_abc (new_height, new_width, 4);
     if (!pchNewPixels) {
         /* Not enough memory for the pixels!
          * Everything remains the same!
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 4c8e09e..0740ebc 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -381,7 +381,7 @@ _cairo_path_create_internal (cairo_path_
 	return (cairo_path_t*) &_cairo_path_nil;
     }
 
-    path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
+    path->data = _cairo_malloc_ab (path->num_data, sizeof (cairo_path_data_t));
     if (path->data == NULL) {
 	free (path);
 	return (cairo_path_t*) &_cairo_path_nil;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 9fafc99..6ead4b2 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -133,8 +133,8 @@ _cairo_gradient_pattern_init_copy (cairo
 	pattern->stops = pattern->stops_embedded;
     else if (other->stops)
     {
-	pattern->stops = malloc (other->stops_size *
-				 sizeof (pixman_gradient_stop_t));
+	pattern->stops = _cairo_malloc_ab (other->stops_size,
+					 sizeof (pixman_gradient_stop_t));
 	if (pattern->stops == NULL) {
 	    pattern->stops_size = 0;
 	    pattern->n_stops = 0;
@@ -757,7 +757,7 @@ _cairo_pattern_gradient_grow (cairo_grad
     assert (pattern->n_stops <= pattern->stops_size);
 
     if (pattern->stops == pattern->stops_embedded) {
-	new_stops = malloc (new_size * sizeof (pixman_gradient_stop_t));
+	new_stops = _cairo_malloc_ab (new_size, sizeof (pixman_gradient_stop_t));
 	if (new_stops)
 	    memcpy (new_stops, pattern->stops, old_size * sizeof (pixman_gradient_stop_t));
     } else {
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 1e73c4c..dc5cda5 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1262,7 +1262,7 @@ _cairo_pdf_surface_emit_pattern_stops (c
     color_function->id = 0;
     alpha_function->id = 0;
 
-    allstops = malloc ((pattern->n_stops + 2) * sizeof (cairo_pdf_color_stop_t));
+    allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_pdf_color_stop_t));
     if (allstops == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
@@ -2726,13 +2726,13 @@ _cairo_pdf_surface_emit_type3_font_subse
     cairo_box_t font_bbox = {{0,0},{0,0}};
     cairo_box_t bbox = {{0,0},{0,0}};
 
-    glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t));
+    glyphs = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (cairo_pdf_resource_t));
     if (glyphs == NULL) {
 	_cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
 	return CAIRO_STATUS_NO_MEMORY;
     }
 
-    widths = malloc (font_subset->num_glyphs * sizeof (double));
+    widths = _cairo_malloc_ab (font_subset->num_glyphs, sizeof (double));
     if (widths == NULL) {
         free (glyphs);
 	_cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index ec9eb7a..9392322 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -78,7 +78,7 @@ _cairo_pen_init (cairo_pen_t	*pen,
 						    radius,
 						    ctm);
 
-    pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
+    pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t));
     if (pen->vertices == NULL) {
 	return CAIRO_STATUS_NO_MEMORY;
     }
@@ -119,7 +119,7 @@ _cairo_pen_init_copy (cairo_pen_t *pen, 
     *pen = *other;
 
     if (pen->num_vertices) {
-	pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
+	pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t));
 	if (pen->vertices == NULL) {
 	    return CAIRO_STATUS_NO_MEMORY;
 	}
diff --git a/src/cairo-png.c b/src/cairo-png.c
index 35db3d9..761fb3f 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -128,7 +128,7 @@ write_png (cairo_surface_t	*surface,
     else if (status != CAIRO_STATUS_SUCCESS)
 	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
 
-    rows = malloc (image->height * sizeof(png_byte*));
+    rows = _cairo_malloc_ab (image->height, sizeof(png_byte*));
     if (rows == NULL) {
         status = CAIRO_STATUS_NO_MEMORY;
 	goto BAIL1;
@@ -429,11 +429,11 @@ read_png (png_rw_ptr	read_func,
     png_read_update_info (png, info);
 
     pixel_size = 4;
-    data = malloc (png_width * png_height * pixel_size);
+    data = _cairo_malloc_abc (png_height, png_width, pixel_size);
     if (data == NULL)
 	goto BAIL;
 
-    row_pointers = malloc (png_height * sizeof(char *));
+    row_pointers = _cairo_malloc_ab (png_height, sizeof(char *));
     if (row_pointers == NULL)
 	goto BAIL;
 
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index e9fc78b..726884a 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -93,7 +93,7 @@ _cairo_polygon_grow (cairo_polygon_t *po
     assert (polygon->num_edges <= polygon->edges_size);
 
     if (polygon->edges == polygon->edges_embedded) {
-	new_edges = malloc (new_size * sizeof (cairo_edge_t));
+	new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
 	if (new_edges)
 	    memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t));
     } else {
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 919a498..2da20d4 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2037,7 +2037,7 @@ _cairo_ps_surface_stroke (void			*abstra
 	 * can modify some of the values.
 	 */
 	if (num_dashes % 2) {
-	    dash = malloc (2 * num_dashes * sizeof (double));
+	    dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double));
 	    if (dash == NULL)
 		return CAIRO_STATUS_NO_MEMORY;
 
@@ -2215,7 +2215,7 @@ _cairo_ps_surface_show_glyphs (void		   
     num_glyphs_unsigned = num_glyphs;
 
     _cairo_ps_surface_emit_pattern (surface, source);
-    glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t));
+    glyph_ids = _cairo_malloc_ab (num_glyphs_unsigned, sizeof (cairo_ps_glyph_id_t));
     if (glyph_ids == NULL)
         return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 06c8ba8..b63b139 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1255,7 +1255,7 @@ _cairo_quartz_surface_stroke (void *abst
 	float *fdash = sdash;
 	unsigned int k;
 	if (style->num_dashes > STATIC_DASH)
-	    fdash = malloc (sizeof(float)*style->num_dashes);
+	    fdash = _cairo_malloc_ab (style->num_dashes, sizeof (float));
 
 	for (k = 0; k < style->num_dashes; k++)
 	    fdash[k] = (float) style->dash[k];
@@ -1394,8 +1394,8 @@ _cairo_quartz_surface_show_glyphs (void 
     CGContextSetFontSize (surface->cgContext, 1.0);
 
     if (num_glyphs > STATIC_BUF_SIZE) {
-	cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
-	cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
+	cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof(CGGlyph));
+	cg_advances = (CGSize*) _cairo_malloc_ab (num_glyphs, sizeof(CGSize));
     }
 
     xprev = glyphs[0].x;
@@ -1711,7 +1711,7 @@ cairo_quartz_surface_create (cairo_forma
 	return (cairo_surface_t*) &_cairo_surface_nil;
     }
 
-    imageData = malloc (height * stride);
+    imageData = _cairo_malloc_ab (height, stride);
     if (!imageData) {
 	CGColorSpaceRelease (cgColorspace);
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 65b1cdc..ea2e63a 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -390,7 +390,7 @@ _cairo_sub_font_collect (void *entry, vo
 	subset.num_glyphs = collection->num_glyphs;
         /* No need to check for out of memory here. If to_unicode is NULL, the PDF
          * surface does not emit an ToUnicode stream */
-        subset.to_unicode = malloc (collection->num_glyphs*sizeof(unsigned long));
+        subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long));
         if (subset.to_unicode) {
             for (j = 0; j < collection->num_glyphs; j++) {
                 /* default unicode character required when mapping fails */
@@ -622,7 +622,7 @@ _cairo_scaled_font_subsets_foreach_inter
     if (! collection.glyphs_size)
 	return CAIRO_STATUS_SUCCESS;
 
-    collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
+    collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
     if (collection.glyphs == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 7a47219..ef70a38 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -927,7 +927,7 @@ _cairo_scaled_font_text_to_glyphs (cairo
     if (status)
 	goto DONE;
 
-    *glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t)));
+    *glyphs = (cairo_glyph_t *) _cairo_malloc_ab ((*num_glyphs), sizeof (cairo_glyph_t));
 
     if (*glyphs == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index bf87770..db748b3 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -109,7 +109,7 @@ _cairo_spline_grow (cairo_spline_t *spli
     assert (spline->num_points <= spline->points_size);
 
     if (spline->points == spline->points_embedded) {
-	new_points = malloc (new_size * sizeof (cairo_point_t));
+	new_points = _cairo_malloc_ab (new_size, sizeof (cairo_point_t));
 	if (new_points)
 	    memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t));
     } else {
diff --git a/src/cairo-stroke-style.c b/src/cairo-stroke-style.c
index a150906..2eccb80 100644
--- a/src/cairo-stroke-style.c
+++ b/src/cairo-stroke-style.c
@@ -62,7 +62,7 @@ _cairo_stroke_style_init_copy (cairo_str
     if (other->dash == NULL) {
 	style->dash = NULL;
     } else {
-	style->dash = malloc (style->num_dashes * sizeof (double));
+	style->dash = _cairo_malloc_ab (style->num_dashes, sizeof (double));
 	if (style->dash == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 8898aee..bf7ae99 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1166,7 +1166,7 @@ _cairo_surface_fallback_fill_rectangles 
     /* If the fetched image isn't at 0,0, we need to offset the rectangles */
 
     if (state.image_rect.x != 0 || state.image_rect.y != 0) {
-	offset_rects = malloc (sizeof (cairo_rectangle_int16_t) * num_rects);
+      offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int16_t));
 	if (offset_rects == NULL) {
 	    status = CAIRO_STATUS_NO_MEMORY;
 	    goto DONE;
@@ -1222,7 +1222,7 @@ _cairo_surface_fallback_composite_trapez
     /* If the destination image isn't at 0,0, we need to offset the trapezoids */
 
     if (state.image_rect.x != 0 || state.image_rect.y != 0) {
-	offset_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
+	offset_traps = _cairo_malloc_ab (num_traps, sizeof (cairo_trapezoid_t));
 	if (!offset_traps) {
 	    status = CAIRO_STATUS_NO_MEMORY;
 	    goto DONE;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index d7ef33f..447cb62 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1245,7 +1245,7 @@ _cairo_surface_fill_region (cairo_surfac
 
     rects = stack_rects;
     if (num_rects > ARRAY_LENGTH (stack_rects)) {
-	rects = malloc (sizeof (cairo_rectangle_int16_t) * num_rects);
+	rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int16_t));
 	if (!rects)
 	    return CAIRO_STATUS_NO_MEMORY;
     }
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 483440f..9d5ed6a 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1220,7 +1220,7 @@ _cairo_svg_surface_emit_pattern_stops (c
 
     if (emulate_reflect || reverse_stops) {
 	n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops;
-	stops = malloc (sizeof (pixman_gradient_stop_t) * n_stops);
+	stops = _cairo_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
 
 	for (i = 0; i < pattern->n_stops; i++) {
 	    if (reverse_stops) {
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index dd885c5..78e65ab 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -260,7 +260,7 @@ _cairo_traps_grow (cairo_traps_t *traps)
 	return traps->status;
 
     if (traps->traps == traps->traps_embedded) {
-	new_traps = malloc (new_size * sizeof (cairo_trapezoid_t));
+	new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
 	if (new_traps)
 	    memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
     } else {
diff --git a/src/cairo-unicode.c b/src/cairo-unicode.c
index 9abb0eb..1d1c00a 100644
--- a/src/cairo-unicode.c
+++ b/src/cairo-unicode.c
@@ -240,7 +240,7 @@ _cairo_utf8_to_ucs4 (const unsigned char
 	in = UTF8_NEXT_CHAR (in);
     }
 
-    str32 = malloc (sizeof (uint32_t) * (n_chars + 1));
+    str32 = _cairo_malloc_ab (n_chars + 1, sizeof (uint32_t));
     if (!str32)
 	return CAIRO_STATUS_NO_MEMORY;
 
@@ -307,7 +307,7 @@ _cairo_utf8_to_utf16 (const unsigned cha
 	in = UTF8_NEXT_CHAR (in);
     }
 
-    str16 = malloc (sizeof (uint16_t) * (n16 + 1));
+    str16 = _cairo_malloc_ab (n16 + 1, sizeof (uint16_t));
     if (!str16)
 	return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index e1f263b..681dba7 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -613,8 +613,8 @@ _cairo_win32_scaled_font_text_to_glyphs 
 	    dx = NULL;
 	}
 
-	glyph_indices = malloc (sizeof (WCHAR) * buffer_size);
-	dx = malloc (sizeof (int) * buffer_size);
+	glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR));
+	dx = _cairo_malloc_ab (buffer_size, sizeof (int));
 	if (!glyph_indices || !dx) {
 	    status = CAIRO_STATUS_NO_MEMORY;
 	    goto FAIL2;
@@ -645,7 +645,7 @@ _cairo_win32_scaled_font_text_to_glyphs 
     }
 
     *num_glyphs = gcp_results.nGlyphs;
-    *glyphs = malloc (sizeof (cairo_glyph_t) * gcp_results.nGlyphs);
+    *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
     if (!*glyphs) {
 	status = CAIRO_STATUS_NO_MEMORY;
 	goto FAIL2;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 450887a..7f86eb8 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -186,7 +186,7 @@ _create_dc_and_bitmap (cairo_win32_surfa
     }
 
     if (num_palette > 2) {
-	bitmap_info = malloc (sizeof (BITMAPINFOHEADER) + num_palette * sizeof (RGBQUAD));
+	bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
 	if (!bitmap_info)
 	    return CAIRO_STATUS_NO_MEMORY;
     } else {
@@ -1546,8 +1546,8 @@ _cairo_win32_surface_show_glyphs (void		
     SetBkMode(dst->dc, TRANSPARENT);
 
     if (num_glyphs > STACK_GLYPH_SIZE) {
-	glyph_buf = (WORD *)malloc(num_glyphs * sizeof(WORD));
-        dxy_buf = (int *)malloc(num_glyphs * 2 * sizeof(int));
+	glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD));
+        dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2);
     }
 
     /* It is vital that dx values for dxy_buf are calculated from the delta of
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index f929040..f16de3f 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -403,7 +403,7 @@ _get_image_surface (cairo_xcb_surface_t 
     bpp = _bits_per_pixel(surface->dpy, imagerep->depth);
     bytes_per_line = _bytes_per_line(surface->dpy, surface->width, bpp);
 
-    data = malloc (bytes_per_line * surface->height);
+    data = _cairo_malloc_ab (surface->height, bytes_per_line);
     if (data == NULL) {
 	free (imagerep);
 	return CAIRO_STATUS_NO_MEMORY;
@@ -1328,7 +1328,7 @@ _create_trapezoid_mask (cairo_xcb_surfac
     mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE);
     solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
 
-    offset_traps = malloc (sizeof (xcb_render_trapezoid_t) * num_traps);
+    offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t));
     if (!offset_traps)
 	return XCB_NONE;
 
@@ -1515,7 +1515,7 @@ _cairo_xcb_surface_set_clip_region (void
 
 	n_boxes = pixman_region_num_rects (region);
 	if (n_boxes > 0) {
-	    rects = malloc (sizeof(xcb_rectangle_t) * n_boxes);
+	    rects = _cairo_malloc_ab (n_boxes, sizeof(xcb_rectangle_t));
 	    if (rects == NULL)
 		return CAIRO_STATUS_NO_MEMORY;
 	} else {
@@ -2360,7 +2360,7 @@ _cairo_xcb_surface_show_glyphs (void    
     /* We make a copy of the glyphs so that we can elide any size-zero
      * glyphs to workaround an X server bug, (present in at least Xorg
      * 7.1 without EXA). */
-    output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t));
+    output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
     if (output_glyphs == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
 
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 39175bd..3e77165 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1579,7 +1579,7 @@ _create_trapezoid_mask (cairo_xlib_surfa
     mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE);
     solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
 
-    offset_traps = malloc (sizeof (XTrapezoid) * num_traps);
+    offset_traps = _cairo_malloc_ab (num_traps, sizeof (XTrapezoid));
     if (!offset_traps)
 	return None;
 
@@ -1760,7 +1760,7 @@ _cairo_xlib_surface_set_clip_region (voi
 
 	n_boxes = pixman_region_num_rects (region);
 	if (n_boxes > ARRAY_LENGTH (surface->embedded_clip_rects)) {
-	    rects = malloc (sizeof(XRectangle) * n_boxes);
+	    rects = _cairo_malloc_ab (n_boxes, sizeof(XRectangle));
 	    if (rects == NULL)
 		return CAIRO_STATUS_NO_MEMORY;
 	}else {
@@ -2815,7 +2815,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (c
     if (num_elts <= STACK_ELTS_LEN) {
       elts = stack_elts;
     } else {
-      elts = malloc (num_elts * sizeof (XGlyphElt8));
+      elts = _cairo_malloc_ab (num_elts, sizeof (XGlyphElt8));
       if (elts == NULL)
 	  return CAIRO_STATUS_NO_MEMORY;
     }
diff --git a/src/cairoint.h b/src/cairoint.h
index 07846b8..21d43d9 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -181,6 +181,7 @@ do {					\
 
 #include "cairo-mutex-private.h"
 #include "cairo-wideint-private.h"
+#include "cairo-malloc-private.h"
 
 typedef int32_t		cairo_fixed_16_16_t;
 typedef cairo_int64_t	cairo_fixed_32_32_t;


More information about the cairo-commit mailing list