From 883d9725e0f844e7d5cc4c50c75a812b5435702b Mon Sep 17 00:00:00 2001 From: Rich Walsh Date: Sat, 7 Aug 2010 03:01:56 +0300 Subject: [PATCH] os2: Fix buffer allocator behaviour on arithmetic overflow. On arithmetic overflow the buffer allocator would attempt to allocate zero bytes instead of failing the allocation. Depending on the implementation of the underlying allocator being proxied, this may result in an allocation of a zero length buffer, causing all kinds of grief. This patch causes arithmetic overflows to explicitly fail the allocation. Thread "OS/2 surface fixes" on cairo-l: http://lists.cairographics.org/archives/cairo/2010-July/020343.html --- src/cairo-os2-surface.c | 58 ++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c index 1df61fd9c..ead5f9970 100644 --- a/src/cairo-os2-surface.c +++ b/src/cairo-os2-surface.c @@ -171,43 +171,35 @@ cairo_os2_fini (void) */ void *_buffer_alloc (size_t a, size_t b, const unsigned int size) { - /* check length like in the _cairo_malloc_abc macro, but we can leave - * away the unsigned casts as our arguments are unsigned already - */ - size_t nbytes = b && - a >= INT32_MAX / b ? 0 : size && - a*b >= INT32_MAX / size ? 0 : a * b * size; - void *buffer = NULL; -#ifdef OS2_USE_PLATFORM_ALLOC - APIRET rc = NO_ERROR; + size_t nbytes; + void *buffer = NULL; - rc = DosAllocMem ((PPVOID)&buffer, - nbytes, -#ifdef OS2_HIGH_MEMORY /* only if compiled with high-memory support, */ - OBJ_ANY | /* we can allocate anywhere! */ -#endif - PAG_READ | PAG_WRITE | PAG_COMMIT); - if (rc != NO_ERROR) { - /* should there for some reason be another error, let's return - * a null surface and free the buffer again, because that's - * how a malloc failure would look like - */ - if (rc != ERROR_NOT_ENOUGH_MEMORY && buffer) { - DosFreeMem (buffer); - } + if (!a || !b || !size || + a >= INT32_MAX / b || a*b >= INT32_MAX / size) { return NULL; } -#else - buffer = malloc (nbytes); + nbytes = a * b * size; + +#ifdef OS2_USE_PLATFORM_ALLOC + /* Using OBJ_ANY on a machine that isn't configured for hi-mem + * will cause ERROR_INVALID_PARAMETER. If this occurs, or this + * build doesn't have hi-mem enabled, fall back to using lo-mem. + */ +#ifdef OS2_HIGH_MEMORY + if (!DosAllocMem (&buffer, nbytes, + OBJ_ANY | PAG_READ | PAG_WRITE | PAG_COMMIT)) + return buffer; +#endif + if (DosAllocMem (&buffer, nbytes, + PAG_READ | PAG_WRITE | PAG_COMMIT)) + return NULL; +#else + /* Clear the malloc'd buffer the way DosAllocMem() does. */ + buffer = malloc (nbytes); + if (buffer) { + memset (buffer, 0, nbytes); + } #endif - - /* This does not seem to be needed, malloc'd space is usually - * already zero'd out! - */ - /* - * memset (buffer, 0x00, nbytes); - */ - return buffer; }