diff --git a/lib/ds/plarena.c b/lib/ds/plarena.c --- a/lib/ds/plarena.c +++ b/lib/ds/plarena.c @@ -88,16 +88,19 @@ PR_IMPLEMENT(void) PL_InitArenaPool( align = PL_ARENA_DEFAULT_ALIGN; if (align < sizeof(pmasks)/sizeof(pmasks[0])) pool->mask = pmasks[align]; else pool->mask = PR_BITMASK(PR_CeilingLog2(align)); pool->first.next = NULL; + /* Set all three addresses in pool->first to the same dummy value. + * These addresses are only compared with each other, but never + * dereferenced. */ pool->first.base = pool->first.avail = pool->first.limit = (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; /* * Compute the net size so that each arena's gross size is |size|. * sizeof(PLArena) + pool->mask is the header and alignment slop * that PL_ArenaAllocate adds to the net size. */ @@ -139,20 +142,24 @@ PR_IMPLEMENT(void) PL_InitArenaPool( ** See also: bugzilla: 45343. ** */ PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb) { PLArena *a; char *rp; /* returned pointer */ + PRUint32 nbOld; PR_ASSERT((nb & pool->mask) == 0); + nbOld = nb; nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */ + if (nb < nbOld) + return NULL; /* attempt to allocate from arenas at pool->current */ { a = pool->current; do { if ( nb <= a->limit - a->avail ) { pool->current = a; rp = (char *)a->avail; @@ -203,16 +210,17 @@ PR_IMPLEMENT(void *) PL_ArenaAllocate(PL a = (PLArena*)PR_MALLOC(sz); } if ( NULL != a ) { a->limit = (PRUword)a + sz; a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1); PL_MAKE_MEM_NOACCESS((void*)a->avail, a->limit - a->avail); rp = (char *)a->avail; a->avail += nb; + PR_ASSERT(a->avail <= a->limit); /* the newly allocated arena is linked after pool->current * and becomes pool->current */ a->next = pool->current->next; pool->current->next = a; pool->current = a; if ( NULL == pool->first.next ) pool->first.next = a; PL_COUNT_ARENA(pool,++); @@ -225,16 +233,18 @@ PR_IMPLEMENT(void *) PL_ArenaAllocate(PL return(NULL); } /* --- end PL_ArenaAllocate() --- */ PR_IMPLEMENT(void *) PL_ArenaGrow( PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr) { void *newp; + if (PR_UINT32_MAX - size < incr) + return NULL; PL_ARENA_ALLOCATE(newp, pool, size + incr); if (newp) memcpy(newp, p, size); return newp; } static void ClearArenaList(PLArena *a, PRInt32 pattern) { diff --git a/lib/ds/plarena.h b/lib/ds/plarena.h --- a/lib/ds/plarena.h +++ b/lib/ds/plarena.h @@ -132,44 +132,49 @@ void __asan_unpoison_memory_region(void PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1) #else #define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + (pool)->mask) & ~(pool)->mask) #endif #define PL_ARENA_ALLOCATE(p, pool, nb) \ PR_BEGIN_MACRO \ PLArena *_a = (pool)->current; \ - PRUint32 _nb = PL_ARENA_ALIGN(pool, nb); \ + PRUint32 _nb = PL_ARENA_ALIGN(pool, (PRUint32)nb); \ PRUword _p = _a->avail; \ - PRUword _q = _p + _nb; \ - if (_q > _a->limit) { \ + if (_nb < (PRUint32)nb) { \ + _p = 0; \ + } else if (_nb > (_a->limit - _a->avail)) { \ _p = (PRUword)PL_ArenaAllocate(pool, _nb); \ } else { \ - _a->avail = _q; \ + _a->avail += _nb; \ } \ p = (void *)_p; \ - PL_MAKE_MEM_UNDEFINED(p, nb); \ - PL_ArenaCountAllocation(pool, nb); \ + if (p) { \ + PL_MAKE_MEM_UNDEFINED(p, (PRUint32)nb); \ + PL_ArenaCountAllocation(pool, (PRUint32)nb); \ + } \ PR_END_MACRO #define PL_ARENA_GROW(p, pool, size, incr) \ PR_BEGIN_MACRO \ PLArena *_a = (pool)->current; \ - PRUint32 _incr = PL_ARENA_ALIGN(pool, incr); \ - PRUword _p = _a->avail; \ - PRUword _q = _p + _incr; \ - if (_p == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \ - _q <= _a->limit) { \ - PL_MAKE_MEM_UNDEFINED((unsigned char *)(p) + size, incr); \ - _a->avail = _q; \ - PL_ArenaCountInplaceGrowth(pool, size, incr); \ + PRUint32 _incr = PL_ARENA_ALIGN(pool, (PRUint32)incr); \ + if (_incr < (PRUint32)incr) { \ + p = NULL; \ + } else if (_a->avail == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \ + _incr <= (_a->limit - _a->avail)) { \ + PL_MAKE_MEM_UNDEFINED((unsigned char *)(p) + size, (PRUint32)incr); \ + _a->avail += _incr; \ + PL_ArenaCountInplaceGrowth(pool, size, (PRUint32)incr); \ } else { \ - p = PL_ArenaGrow(pool, p, size, incr); \ + p = PL_ArenaGrow(pool, p, size, (PRUint32)incr); \ } \ - PL_ArenaCountGrowth(pool, size, incr); \ + if (p) {\ + PL_ArenaCountGrowth(pool, size, (PRUint32)incr); \ + } \ PR_END_MACRO #define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail) #define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q)) #define PL_CLEAR_UNUSED_PATTERN(a, pattern) \ PR_BEGIN_MACRO \ PR_ASSERT((a)->avail <= (a)->limit); \