diff --git a/CODING_STYLE b/CODING_STYLE index 2aef41c..dac06c2 100644 --- a/CODING_STYLE +++ b/CODING_STYLE @@ -243,3 +243,34 @@ 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 _cairo_malloc2() and _cairo_malloc3() to avoid these +cases; these functions check for overflow and will return NULL in that +case. + + malloc (a * s) => _cairo_malloc2 (a, s) + e.g. malloc (num_elts * sizeof(some_type)) => + _cairo_malloc2 (num_elts, sizeof(some_type)) + + malloc (a * s * k) => _cairo_malloc3 (a, s, k) + e.g. malloc (width * height * 4) => + _cairo_malloc3 (width, height, 4) + +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. For example: + + malloc (sizeof(header) + n_items * sizeof(item)) + +should become + + size_t size = n_items * sizeof(item); + if (size / n_items != sizeof(item) || + UINT32_MAX - size < sizeof(header)) + return ERROR; + data = malloc(size + sizeof(header)); diff --git a/pixman/src/fbcompose.c b/pixman/src/fbcompose.c index 4197e34..a247124 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_malloc2 (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_malloc3 (width, sizeof(CARD32), 3); n = pixman_region_num_rects (®ion); pbox = pixman_region_rects (®ion); diff --git a/pixman/src/icimage.c b/pixman/src/icimage.c index 61a84c5..6b24147 100644 --- a/pixman/src/icimage.c +++ b/pixman/src/icimage.c @@ -25,6 +25,19 @@ #include "pixman-xserver-compat.h" +static void * +struct_array_alloc (size_t k, size_t n, size_t sz) +{ + size_t size = n * sz; + if (size / n != sz) + return NULL; + + if (UINT32_MAX - size < k) + return NULL; + + return malloc (size + k); +} + pixman_image_t * pixman_image_create (pixman_format_t *format, int width, @@ -215,8 +228,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 = struct_array_alloc (sizeof (pixman_linear_gradient_image_t), + n_stops, sizeof (pixman_gradient_stop_t)); if (!linear) { free (image); @@ -259,8 +272,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 = struct_array_alloc (sizeof (pixman_radial_gradient_image_t), + n_stops, sizeof (pixman_gradient_stop_t)); if (!radial) { free (image); diff --git a/pixman/src/icutil.c b/pixman/src/icutil.c index e9f561c..45f5489 100644 --- a/pixman/src/icutil.c +++ b/pixman/src/icutil.c @@ -285,3 +285,35 @@ fbStippleTable(int bits) } return NULL; } + +void * +_pixman_malloc2 (size_t nmemb, size_t size) +{ + size_t total_size; + if (nmemb <= 0 || size <= 0) + return NULL; + + total_size = nmemb * size; + if (total_size / size != nmemb) + return NULL; + + return malloc (total_size); +} + +void * +_pixman_malloc3 (size_t nmemb, size_t size, size_t k) +{ + size_t size1, total_size; + if (nmemb <= 0 || size <= 0 || k <= 0) + return NULL; + + size1 = nmemb * size; + if (size1 / size != nmemb) + return NULL; + + total_size = size1 * k; + if (total_size / k != size1) + return NULL; + + return malloc (total_size); +} diff --git a/pixman/src/pixman.h b/pixman/src/pixman.h index 8a2dd18..a8a4c4c 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..9ff913d 100644 --- a/pixman/src/pixmanint.h +++ b/pixman/src/pixmanint.h @@ -1073,4 +1073,10 @@ typedef xFixed_16_16 xFixed; (*((a)+2) = (CARD8) ((v) >> 16)))) #endif +pixman_private void * +_pixman_malloc2 (size_t nmemb, size_t size); + +pixman_private void * +_pixman_malloc3 (size_t nmemb, size_t size, size_t k); + #endif /* _PIXMANINT_H_ */ diff --git a/pixman/src/pixregion.c b/pixman/src/pixregion.c index 0c214cb..6aacd48 100644 --- a/pixman/src/pixregion.c +++ b/pixman/src/pixregion.c @@ -146,7 +146,31 @@ pixman_break (pixman_region16_t *pReg); ((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 (size / n != sizeof(pixman_box16_t)) + return 0; + + if (UINT32_MAX - size < sizeof(pixman_region16_data_t)) + 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) \ @@ -183,7 +207,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); \ @@ -343,11 +370,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 **) ®ion->data); if (!region->data) return pixman_break (region); region->data->numRects = 1; @@ -355,7 +383,7 @@ pixman_rect_alloc(pixman_region16_t * region, int n) } else if (!region->data->size) { - region->data = allocData(n); + allocData(n, (void **) ®ion->data); if (!region->data) return pixman_break (region); region->data->numRects = 0; @@ -369,7 +397,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; @@ -395,7 +426,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; @@ -806,8 +837,10 @@ pixman_op( AppendRegions(newReg, r2BandEnd, r2End); } - if (oldData) + if (oldData) { free(oldData); + oldData = NULL; + } if (!(numRects = newReg->data->numRects)) { @@ -1464,7 +1497,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_malloc2(4, sizeof(RegionInfo)); if (!ri) return pixman_break (badreg); sizeRI = 4; @@ -1526,9 +1559,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; @@ -1630,7 +1667,7 @@ pixman_region_rectsToRegion(nrects, prect, ctype) } return region; } - pData = allocData(nrects); + allocData(nrects, &pData); if (!pData) { pixman_break (region); @@ -2138,7 +2175,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 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-array.c b/src/cairo-array.c index ff8cce4..0273065 100644 --- a/src/cairo-array.c +++ b/src/cairo-array.c @@ -472,3 +472,62 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array, return CAIRO_STATUS_SUCCESS; } + +/** + * _cairo_malloc2: + * @nmemb: the number of members to allocate + * @size: size of each member + * + * Allocates @nmemb*@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(). + * + * Return value: A pointer to the newly allocated memory, or %NULL in + * case of malloc() failure or overflow. + */ +void * +_cairo_malloc2 (size_t nmemb, size_t size) +{ + size_t total_size; + if (nmemb <= 0 || size <= 0) + return NULL; + + total_size = nmemb * size; + if (total_size / size != nmemb) + return NULL; + + return malloc (total_size); +} + +/** + * _cairo_malloc3: + * @nmemb: the number of members to allocate + * @size: size of each member + * @k: additional multiplication factor + * + * Allocates @nmemb*@size*@k 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(). + * + * Return value: A pointer to the newly allocated memory, or %NULL in + * case of malloc() failure or overflow. + */ +void * +_cairo_malloc3 (size_t nmemb, size_t size, size_t k) +{ + size_t size1, total_size; + if (nmemb <= 0 || size <= 0 || k <= 0) + return NULL; + + size1 = nmemb * size; + if (size1 / size != nmemb) + return NULL; + + total_size = size1 * k; + if (total_size / k != size1) + return NULL; + + return malloc (total_size); +} diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 34560d2..19228aa 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -796,7 +796,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_malloc2(*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..75eba7b 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_malloc2 (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_malloc2 (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_malloc2 (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-clip.c b/src/cairo-clip.c index 60f2418..fee4cd4 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_malloc2 (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 3dc3863..ccdfc6a 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_malloc2 (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..15744e6 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_malloc2 (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_malloc2 (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..850c7b1 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_malloc2 (height, pf.bytes_per_line); if (!pixels) return CAIRO_STATUS_NO_MEMORY; diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index fc8c545..4a3afe4 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_malloc2 (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_malloc2 (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_malloc2 (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..7650c81 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_malloc2 (num_vertices, sizeof (cairo_hull_t)); if (hull == NULL) return NULL; diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c index 8dbd608..56549f0 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_malloc2 (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_malloc2 (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..0d17335 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_malloc3 (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_malloc3 (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_malloc3 (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..9289196 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_malloc2 (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..1df4a55 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_malloc2 (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_malloc2 (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..7e910f5 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_malloc2 ((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_malloc2 (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_malloc2 (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..4eed833 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_malloc2 (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_malloc2 (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..e8f77ef 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_malloc2 (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_malloc3 (png_height, png_width, pixel_size); if (data == NULL) goto BAIL; - row_pointers = malloc (png_height * sizeof(char *)); + row_pointers = _cairo_malloc2 (png_height, sizeof(char *)); if (row_pointers == NULL) goto BAIL; diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c index e9fc78b..4cbbae1 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_malloc2 (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..cd15f21 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_malloc3 (num_dashes, sizeof (double), 2); 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_malloc2 (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 dc831c1..95fd58a 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -1303,7 +1303,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_malloc2 (style->num_dashes, sizeof (float)); for (k = 0; k < style->num_dashes; k++) fdash[k] = (float) style->dash[k]; @@ -1438,8 +1438,8 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface, CGSize *cg_advances = &cg_advances_static[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_malloc2 (num_glyphs, sizeof(CGGlyph)); + cg_advances = (CGSize*) _cairo_malloc2 (num_glyphs, sizeof(CGSize)); } float xprev = glyphs[0].x; @@ -1755,7 +1755,7 @@ cairo_quartz_surface_create (cairo_format_t format, return (cairo_surface_t*) &_cairo_surface_nil; } - imageData = malloc (height * stride); + imageData = _cairo_malloc2 (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..c8fa159 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_malloc2 (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_malloc2 (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..d98366c 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_malloc2 ((*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..4adc83c 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_malloc2 (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..b626510 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_malloc2 (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..6ddde95 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_malloc2 (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_malloc2 (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..f625834 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_malloc2 (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..e328411 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_malloc2 (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 f7171dd..0ec2b09 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_malloc2 (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..c6b9035 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_malloc2 (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_malloc2 (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..5dba88b 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_malloc2 (buffer_size, sizeof (WCHAR)); + dx = _cairo_malloc2 (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_malloc2 (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..76145c0 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -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_malloc2 (num_glyphs, sizeof(WORD)); + dxy_buf = (int *) _cairo_malloc3 (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..ded64c0 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_malloc2 (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_malloc2 (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_malloc2 (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_malloc2 (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 db5c155..d7d3a3d 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -1566,7 +1566,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_malloc2 (num_traps, sizeof (XTrapezoid)); if (!offset_traps) return None; @@ -1747,7 +1747,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_malloc2 (n_boxes, sizeof(XRectangle)); if (rects == NULL) return CAIRO_STATUS_NO_MEMORY; }else { @@ -2797,7 +2797,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_malloc2 (num_elts, sizeof (XGlyphElt8)); if (elts == NULL) return CAIRO_STATUS_NO_MEMORY; } diff --git a/src/cairoint.h b/src/cairoint.h index 07846b8..57ffcb6 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -478,6 +478,12 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array, cairo_private unsigned long _cairo_hash_string (const char *c); +cairo_private void * +_cairo_malloc2 (size_t nmemb, size_t size); + +cairo_private void * +_cairo_malloc3 (size_t nmemb, size_t size, size_t k); + typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t; /*