[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.
This commit is contained in:
Vladimir Vukicevic 2007-06-19 13:15:21 -07:00 committed by Vladimir Vukicevic
parent fc34073464
commit 5c7d2d14d7
41 changed files with 308 additions and 89 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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_ */

View file

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

View file

@ -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_ */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;
data = malloc (num_glyphs * sizeof (void *) +
num_glyphs * sizeof (glitz_float_t) * 16);
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 (size1 + size2);
if (!data)
goto FAIL1;

View file

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

View file

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

104
src/cairo-malloc-private.h Normal file
View file

@ -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 */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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