| diff --git a/nspr/lib/ds/plarena.c b/nspr/lib/ds/plarena.c |
| index 95e1931..689496d 100644 |
| --- a/nspr/lib/ds/plarena.c |
| +++ b/nspr/lib/ds/plarena.c |
| @@ -93,6 +93,9 @@ PR_IMPLEMENT(void) PL_InitArenaPool( |
| 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; |
| @@ -144,10 +147,14 @@ 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 */ |
| { |
| @@ -208,6 +215,7 @@ PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb) |
| 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; |
| @@ -230,6 +238,8 @@ PR_IMPLEMENT(void *) PL_ArenaGrow( |
| { |
| void *newp; |
| |
| + if (PR_UINT32_MAX - size < incr) |
| + return NULL; |
| PL_ARENA_ALLOCATE(newp, pool, size + incr); |
| if (newp) |
| memcpy(newp, p, size); |
| diff --git a/nspr/lib/ds/plarena.h b/nspr/lib/ds/plarena.h |
| index 8dcfb3e..3e51f83 100644 |
| --- a/nspr/lib/ds/plarena.h |
| +++ b/nspr/lib/ds/plarena.h |
| @@ -139,32 +139,37 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); |
| PLArena *_a = (pool)->current; \ |
| PRUint32 _nb = PL_ARENA_ALIGN(pool, nb); \ |
| PRUword _p = _a->avail; \ |
| - PRUword _q = _p + _nb; \ |
| - if (_q > _a->limit) { \ |
| + if (_nb < 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, nb); \ |
| + PL_ArenaCountAllocation(pool, 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) { \ |
| + if (_incr < 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, incr); \ |
| - _a->avail = _q; \ |
| + _a->avail += _incr; \ |
| PL_ArenaCountInplaceGrowth(pool, size, incr); \ |
| } else { \ |
| p = PL_ArenaGrow(pool, p, size, incr); \ |
| } \ |
| - PL_ArenaCountGrowth(pool, size, incr); \ |
| + if (p) {\ |
| + PL_ArenaCountGrowth(pool, size, incr); \ |
| + } \ |
| PR_END_MACRO |
| |
| #define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail) |