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); \