diff options
author | Ryan Sleevi <ryan.sleevi@gmail.com> | 2015-10-15 19:36:01 +0200 |
---|---|---|
committer | Ryan Sleevi <ryan.sleevi@gmail.com> | 2015-10-15 19:36:01 +0200 |
commit | 43e8c8477422ea90704b69c7c2625306470f9a38 (patch) | |
tree | 7f7ba365a184cdcecaa6734db94d9937f6a3c479 | |
parent | 9c1b49afe2effe98b4a2addbeb8c06e631a4d707 (diff) | |
download | nspr-hg-43e8c8477422ea90704b69c7c2625306470f9a38.tar.gz |
Fix bug 1205157, r=wtc
-rw-r--r-- | lib/ds/plarena.c | 10 | ||||
-rw-r--r-- | lib/ds/plarena.h | 27 |
2 files changed, 26 insertions, 11 deletions
diff --git a/lib/ds/plarena.c b/lib/ds/plarena.c index 95e1931e..689496dc 100644 --- a/lib/ds/plarena.c +++ b/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/lib/ds/plarena.h b/lib/ds/plarena.h index 8dcfb3e5..3e51f835 100644 --- a/lib/ds/plarena.h +++ b/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) |