summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Sleevi <ryan.sleevi@gmail.com>2015-10-15 19:36:01 +0200
committerRyan Sleevi <ryan.sleevi@gmail.com>2015-10-15 19:36:01 +0200
commit43e8c8477422ea90704b69c7c2625306470f9a38 (patch)
tree7f7ba365a184cdcecaa6734db94d9937f6a3c479
parent9c1b49afe2effe98b4a2addbeb8c06e631a4d707 (diff)
downloadnspr-hg-43e8c8477422ea90704b69c7c2625306470f9a38.tar.gz
Fix bug 1205157, r=wtc
-rw-r--r--lib/ds/plarena.c10
-rw-r--r--lib/ds/plarena.h27
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)