diff options
author | Wan-Teh Chang <wtc@google.com> | 2013-10-14 17:37:37 -0700 |
---|---|---|
committer | Wan-Teh Chang <wtc@google.com> | 2013-10-14 17:37:37 -0700 |
commit | 17ec8861253f61ed25498a1ea9769c663416706f (patch) | |
tree | e28b4365a78ca38f018e4791c500211fefdd4241 | |
parent | 897f15082519cb9612b892fdfea27581ec9f5d27 (diff) | |
download | nss-hg-17ec8861253f61ed25498a1ea9769c663416706f.tar.gz |
Bug 925100: ensure a size is <= half of the maximum PRUint32 value
before passing it to NSPR memory allocation functions. r=rrelyea.
Adam Langley wrote the first version of the patch.
-rw-r--r-- | lib/util/secport.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/lib/util/secport.c b/lib/util/secport.c index dc44d25ae..106399d24 100644 --- a/lib/util/secport.c +++ b/lib/util/secport.c @@ -69,13 +69,22 @@ PORTCharConversionFunc ucs4Utf8ConvertFunc; PORTCharConversionFunc ucs2Utf8ConvertFunc; PORTCharConversionWSwapFunc ucs2AsciiConvertFunc; +/* NSPR memory allocation functions (PR_Malloc, PR_Calloc, and PR_Realloc) + * use the PRUint32 type for the size parameter. Before we pass a size_t or + * unsigned long size to these functions, we need to ensure it is <= half of + * the maximum PRUint32 value to avoid truncation and catch a negative size. + */ +#define MAX_SIZE (PR_UINT32_MAX >> 1) + void * PORT_Alloc(size_t bytes) { - void *rv; + void *rv = NULL; - /* Always allocate a non-zero amount of bytes */ - rv = (void *)PR_Malloc(bytes ? bytes : 1); + if (bytes <= MAX_SIZE) { + /* Always allocate a non-zero amount of bytes */ + rv = PR_Malloc(bytes ? bytes : 1); + } if (!rv) { ++port_allocFailures; PORT_SetError(SEC_ERROR_NO_MEMORY); @@ -86,9 +95,11 @@ PORT_Alloc(size_t bytes) void * PORT_Realloc(void *oldptr, size_t bytes) { - void *rv; + void *rv = NULL; - rv = (void *)PR_Realloc(oldptr, bytes); + if (bytes <= MAX_SIZE) { + rv = PR_Realloc(oldptr, bytes); + } if (!rv) { ++port_allocFailures; PORT_SetError(SEC_ERROR_NO_MEMORY); @@ -99,10 +110,12 @@ PORT_Realloc(void *oldptr, size_t bytes) void * PORT_ZAlloc(size_t bytes) { - void *rv; + void *rv = NULL; - /* Always allocate a non-zero amount of bytes */ - rv = (void *)PR_Calloc(1, bytes ? bytes : 1); + if (bytes <= MAX_SIZE) { + /* Always allocate a non-zero amount of bytes */ + rv = PR_Calloc(1, bytes ? bytes : 1); + } if (!rv) { ++port_allocFailures; PORT_SetError(SEC_ERROR_NO_MEMORY); @@ -209,6 +222,10 @@ PORT_NewArena(unsigned long chunksize) { PORTArenaPool *pool; + if (chunksize > MAX_SIZE) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return NULL; + } pool = PORT_ZNew(PORTArenaPool); if (!pool) { return NULL; @@ -224,8 +241,6 @@ PORT_NewArena(unsigned long chunksize) return(&pool->arena); } -#define MAX_SIZE 0x7fffffffUL - void * PORT_ArenaAlloc(PLArenaPool *arena, size_t size) { @@ -330,6 +345,11 @@ PORT_ArenaGrow(PLArenaPool *arena, void *ptr, size_t oldsize, size_t newsize) PORTArenaPool *pool = (PORTArenaPool *)arena; PORT_Assert(newsize >= oldsize); + if (newsize > MAX_SIZE) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return NULL; + } + if (ARENAPOOL_MAGIC == pool->magic ) { PZ_Lock(pool->lock); /* Do we do a THREADMARK check here? */ |