summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWan-Teh Chang <wtc@google.com>2013-10-14 17:37:37 -0700
committerWan-Teh Chang <wtc@google.com>2013-10-14 17:37:37 -0700
commit17ec8861253f61ed25498a1ea9769c663416706f (patch)
treee28b4365a78ca38f018e4791c500211fefdd4241
parent897f15082519cb9612b892fdfea27581ec9f5d27 (diff)
downloadnss-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.c40
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? */