зеркало из https://github.com/mozilla/gecko-dev.git
Ensure proper pointer alignment in oversized arena footers (105726, r/sr=jband,shaver).
This commit is contained in:
Родитель
507a096fa9
Коммит
114a9d244c
|
@ -88,6 +88,31 @@ JS_InitArenaPool(JSArenaPool *pool, const char *name, JSUint32 size, JSUint32 al
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An allocation that consumes more than pool->arenasize also has a footer
|
||||||
|
* pointing back to its previous arena's next member. This footer is not
|
||||||
|
* included in [a->base, a->limit), so its space can't be wrongly claimed.
|
||||||
|
*
|
||||||
|
* As the footer is a pointer, it must be well-aligned. If pool->mask is
|
||||||
|
* greater than or equal to POINTER_MASK, the footer starting at a->avail
|
||||||
|
* for an oversized arena a is well-aligned. If pool->mask is less than
|
||||||
|
* POINTER_MASK, we must include enough space in FOOTER_SIZE to align the
|
||||||
|
* back-pointer. Given power-of-two alignment restrictions, that space is
|
||||||
|
* POINTER_MASK - pool->mask.
|
||||||
|
*/
|
||||||
|
#define POINTER_MASK ((jsuword)(JS_ALIGN_OF_POINTER - 1))
|
||||||
|
#define FOOTER_MASK(pool) (((pool)->mask < POINTER_MASK) \
|
||||||
|
? POINTER_MASK \
|
||||||
|
: (jsuword)0)
|
||||||
|
#define FOOTER_SIZE(pool) (sizeof(JSArena **) \
|
||||||
|
+ (((pool)->mask < POINTER_MASK) \
|
||||||
|
? POINTER_MASK - pool->mask \
|
||||||
|
: (jsuword)0))
|
||||||
|
#define FOOTER_ALIGN(pool,q) (((q) + FOOTER_MASK(pool)) & ~FOOTER_MASK(pool))
|
||||||
|
#define FOOTER_ADDRESS(pool,q) ((JSArena ***)FOOTER_ALIGN(pool, q))
|
||||||
|
#define GET_FOOTER(pool,a) (*FOOTER_ADDRESS(pool, (a)->avail))
|
||||||
|
#define SET_FOOTER(pool,a,ap) (*FOOTER_ADDRESS(pool, (a)->avail) = (ap))
|
||||||
|
|
||||||
JS_PUBLIC_API(void *)
|
JS_PUBLIC_API(void *)
|
||||||
JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
||||||
{
|
{
|
||||||
|
@ -95,14 +120,9 @@ JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
||||||
JSUint32 extra, gross, sz;
|
JSUint32 extra, gross, sz;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
/*
|
|
||||||
* An allocation that consumes more than pool->arenasize also has a footer
|
|
||||||
* pointing back to its previous arena's next member. This footer is not
|
|
||||||
* included in [a->base, a->limit), so its space can't be wrongly claimed.
|
|
||||||
*/
|
|
||||||
ap = NULL;
|
ap = NULL;
|
||||||
JS_ASSERT((nb & pool->mask) == 0);
|
JS_ASSERT((nb & pool->mask) == 0);
|
||||||
extra = (nb > pool->arenasize) ? sizeof(JSArena **) : 0;
|
extra = (nb > pool->arenasize) ? FOOTER_SIZE(pool) : 0;
|
||||||
gross = nb + extra;
|
gross = nb + extra;
|
||||||
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
|
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
|
||||||
ap = &a->next;
|
ap = &a->next;
|
||||||
|
@ -154,7 +174,7 @@ JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
||||||
* than (pool->mask + 1) bytes.
|
* than (pool->mask + 1) bytes.
|
||||||
*/
|
*/
|
||||||
if (extra && ap)
|
if (extra && ap)
|
||||||
*(JSArena ***)a->avail = ap;
|
SET_FOOTER(pool, a, ap);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +189,7 @@ JS_ArenaRealloc(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr)
|
||||||
* See JS_ArenaAllocate, the extra variable.
|
* See JS_ArenaAllocate, the extra variable.
|
||||||
*/
|
*/
|
||||||
if (size > pool->arenasize) {
|
if (size > pool->arenasize) {
|
||||||
ap = *(JSArena ***)((jsuword)p + JS_ARENA_ALIGN(pool, size));
|
ap = *FOOTER_ADDRESS(pool, (jsuword)p + JS_ARENA_ALIGN(pool, size));
|
||||||
a = *ap;
|
a = *ap;
|
||||||
} else {
|
} else {
|
||||||
ap = &pool->first.next;
|
ap = &pool->first.next;
|
||||||
|
@ -181,7 +201,7 @@ JS_ArenaRealloc(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr)
|
||||||
aoff = netsize = size + incr;
|
aoff = netsize = size + incr;
|
||||||
JS_ASSERT(netsize > pool->arenasize);
|
JS_ASSERT(netsize > pool->arenasize);
|
||||||
netsize += sizeof *a + pool->mask; /* header and alignment slop */
|
netsize += sizeof *a + pool->mask; /* header and alignment slop */
|
||||||
gross = netsize + sizeof(JSArena **); /* oversized footer holds ap */
|
gross = netsize + FOOTER_SIZE(pool); /* oversized footer holds ap */
|
||||||
a = (JSArena *) realloc(a, gross);
|
a = (JSArena *) realloc(a, gross);
|
||||||
if (!a)
|
if (!a)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -200,7 +220,7 @@ JS_ArenaRealloc(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr)
|
||||||
memmove((void *)a->base, (char *)a + boff, size);
|
memmove((void *)a->base, (char *)a + boff, size);
|
||||||
|
|
||||||
/* Store ap in the oversized load footer. */
|
/* Store ap in the oversized load footer. */
|
||||||
*(JSArena ***)a->avail = ap;
|
SET_FOOTER(pool, a, ap);
|
||||||
return (void *)a->base;
|
return (void *)a->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +315,7 @@ JS_ArenaFreeAllocation(JSArenaPool *pool, void *p, JSUint32 size)
|
||||||
q = (jsuword)p + size;
|
q = (jsuword)p + size;
|
||||||
q = JS_ARENA_ALIGN(pool, q);
|
q = JS_ARENA_ALIGN(pool, q);
|
||||||
if (size > pool->arenasize) {
|
if (size > pool->arenasize) {
|
||||||
ap = *(JSArena ***)q;
|
ap = *FOOTER_ADDRESS(pool, q);
|
||||||
a = *ap;
|
a = *ap;
|
||||||
} else {
|
} else {
|
||||||
ap = &pool->first.next;
|
ap = &pool->first.next;
|
||||||
|
@ -333,8 +353,8 @@ JS_ArenaFreeAllocation(JSArenaPool *pool, void *p, JSUint32 size)
|
||||||
*/
|
*/
|
||||||
*ap = b = a->next;
|
*ap = b = a->next;
|
||||||
if (b && b->avail - b->base > pool->arenasize) {
|
if (b && b->avail - b->base > pool->arenasize) {
|
||||||
JS_ASSERT(*(JSArena ***)b->avail == &a->next);
|
JS_ASSERT(GET_FOOTER(pool, b) == &a->next);
|
||||||
*(JSArena ***)b->avail = ap;
|
SET_FOOTER(pool, b, ap);
|
||||||
}
|
}
|
||||||
JS_CLEAR_ARENA(a);
|
JS_CLEAR_ARENA(a);
|
||||||
JS_COUNT_ARENA(pool,--);
|
JS_COUNT_ARENA(pool,--);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче