summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Vukicevic <vladimir@pobox.com>2007-06-19 13:15:21 -0700
committerVladimir Vukicevic <vladimir@feisty.(none)>2007-06-29 09:46:08 -0700
commit5c7d2d14d78e4dfb1ef6d2c40f0910f177e07360 (patch)
treebb1abcb2f1144059d4444d8db343014e07791593
parentfc34073464c487405b6e2e0a5fa269a1ae15a02a (diff)
[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.
-rw-r--r--CODING_STYLE25
-rw-r--r--pixman/src/fbcompose.c4
-rw-r--r--pixman/src/icimage.c8
-rw-r--r--pixman/src/pixman.h7
-rw-r--r--pixman/src/pixmanint.h17
-rw-r--r--pixman/src/pixregion.c59
-rw-r--r--pixman/src/pixregionint.h1
-rw-r--r--src/cairo-atsui-font.c2
-rw-r--r--src/cairo-bentley-ottmann.c6
-rw-r--r--src/cairo-beos-surface.cpp4
-rw-r--r--src/cairo-clip.c10
-rw-r--r--src/cairo-directfb-surface.c2
-rw-r--r--src/cairo-ft-font.c4
-rw-r--r--src/cairo-glitz-surface.c34
-rw-r--r--src/cairo-gstate.c6
-rw-r--r--src/cairo-hull.c2
-rw-r--r--src/cairo-malloc-private.h104
-rw-r--r--src/cairo-meta-surface.c4
-rw-r--r--src/cairo-os2-surface.c9
-rw-r--r--src/cairo-path.c2
-rw-r--r--src/cairo-pattern.c6
-rw-r--r--src/cairo-pdf-surface.c6
-rw-r--r--src/cairo-pen.c4
-rw-r--r--src/cairo-png.c6
-rw-r--r--src/cairo-polygon.c2
-rw-r--r--src/cairo-ps-surface.c4
-rw-r--r--src/cairo-quartz-surface.c8
-rw-r--r--src/cairo-scaled-font-subsets.c4
-rw-r--r--src/cairo-scaled-font.c2
-rw-r--r--src/cairo-spline.c2
-rw-r--r--src/cairo-stroke-style.c2
-rw-r--r--src/cairo-surface-fallback.c4
-rw-r--r--src/cairo-surface.c2
-rw-r--r--src/cairo-svg-surface.c2
-rw-r--r--src/cairo-traps.c2
-rw-r--r--src/cairo-unicode.c4
-rw-r--r--src/cairo-win32-font.c6
-rw-r--r--src/cairo-win32-surface.c6
-rw-r--r--src/cairo-xcb-surface.c8
-rw-r--r--src/cairo-xlib-surface.c6
-rw-r--r--src/cairoint.h1
41 files changed, 308 insertions, 89 deletions
diff --git a/CODING_STYLE b/CODING_STYLE
index 2aef41c9..73fe2a9b 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -243,3 +243,28 @@ The return statement is often the best thing to use in a pattern like
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 4197e344..e2823ec3 100644
--- a/pixman/src/fbcompose.c
+++ b/pixman/src/fbcompose.c
@@ -3883,7 +3883,7 @@ static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD3
}
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_t op,
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 61a84c5c..8bcccc48 100644
--- a/pixman/src/icimage.c
+++ b/pixman/src/icimage.c
@@ -215,8 +215,8 @@ pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
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 (const pixman_radial_gradient_t *gradient,
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 feaf60ae..491fc893 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 a10a8342..6ad373eb 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 4cd08e59..1ed3ad70 100644
--- a/pixman/src/pixregion.c
+++ b/pixman/src/pixregion.c
@@ -148,7 +148,31 @@ pixman_rect_alloc(pixman_region16_t * region, int n);
((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->numRects + (n)) > (pReg)->data->size)) \
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 * region, int n)
}
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 * region, int n)
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 *dst, pixman_region16_t *src)
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 * badreg,
/* 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 * badreg,
/* 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, prect, ctype)
}
return region;
}
- pData = allocData(nrects);
+ allocData(nrects, &pData);
if (!pData)
{
pixman_break (region);
@@ -2167,7 +2204,7 @@ pixman_region16_data_copy(pixman_region16_t * dst, pixman_region16_t * src)
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 385a7f23..0ac7db42 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 361e787e..d1196f0e 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -809,7 +809,7 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
*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 b8d97fa2..267459c9 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -754,7 +754,7 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
* 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_polygon (cairo_traps_t *traps,
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 abf094a1..193fa43f 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)
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 60f2418f..83940774 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -634,9 +634,13 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
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 fa31b063..5505501b 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1113,7 +1113,7 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
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 89bb12a4..4dc61eea 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -742,7 +742,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
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 *bitmap,
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 ab154042..de91fc72 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -197,7 +197,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
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 (cairo_pattern_t *pattern,
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 (cairo_scaled_font_t *scaled_font,
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 fc8c5456..901fa586 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -530,7 +530,7 @@ _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dash
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_t *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 *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;
diff --git a/src/cairo-hull.c b/src/cairo-hull.c
index e9d0a155..c56e9e05 100644
--- a/src/cairo-hull.c
+++ b/src/cairo-hull.c
@@ -62,7 +62,7 @@ _cairo_hull_create (cairo_pen_vertex_t *vertices, int num_vertices)
*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 00000000..f503b395
--- /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@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+@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 8dbd6084..30a64e72 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -439,7 +439,7 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface,
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_surface_t *surface,
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 319a7aba..1535de4d 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -296,8 +296,9 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
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_window,
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_surface_t *surface,
}
/* 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 4c8e09e1..0740ebc4 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -381,7 +381,7 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
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 9fafc991..6ead4b2f 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -133,8 +133,8 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
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_gradient_pattern_t *pattern)
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 1e73c4c4..dc5cda5b 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1262,7 +1262,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
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_subset (cairo_pdf_surface_t *surface,
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 ec9eb7ac..9392322d 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, cairo_pen_t *other)
*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 35db3d9a..761fb3f3 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 e9fc78b7..726884a9 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -93,7 +93,7 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
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 919a498c..2da20d46 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2037,7 +2037,7 @@ _cairo_ps_surface_stroke (void *abstract_surface,
* 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 *abstract_surface,
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 06c8ba8c..b63b139f 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1255,7 +1255,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
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 *abstract_surface,
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_format_t format,
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 65b1cdce..ea2e63ae 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, void *closure)
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_internal (cairo_scaled_font_subsets_t
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 7a472191..ef70a389 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -927,7 +927,7 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
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 bf877700..db748b30 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -109,7 +109,7 @@ _cairo_spline_grow (cairo_spline_t *spline)
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 a1509064..2eccb80d 100644
--- a/src/cairo-stroke-style.c
+++ b/src/cairo-stroke-style.c
@@ -62,7 +62,7 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
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 8898aee1..bf7ae995 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1166,7 +1166,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
/* 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_trapezoids (cairo_operator_t op,
/* 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 d7ef33f1..447cb62e 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1245,7 +1245,7 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
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 483440ff..9d5ed6a3 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1220,7 +1220,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
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 dd885c54..78e65ab4 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 9abb0ebc..1d1c00a9 100644
--- a/src/cairo-unicode.c
+++ b/src/cairo-unicode.c
@@ -240,7 +240,7 @@ _cairo_utf8_to_ucs4 (const unsigned char *str,
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 char *str,
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 e1f263b6..681dba77 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -613,8 +613,8 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
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 (void *abstract_font,
}
*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 450887a1..7f86eb8c 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -186,7 +186,7 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
}
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 *surface,
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 f9290409..f16de3f7 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -403,7 +403,7 @@ _get_image_surface (cairo_xcb_surface_t *surface,
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_surface_t *dst,
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 *abstract_surface,
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 *abstract_dst,
/* 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 39175bdf..3e771655 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1579,7 +1579,7 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst,
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 (void *abstract_surface,
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 (cairo_xlib_surface_t *dst,
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 07846b83..21d43d92 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;