fixed crash when resizing property shapes in case of OOM (github issue #129)

This commit is contained in:
Fabrice Bellard 2023-12-27 18:19:06 +01:00
parent 7414e5f67f
commit b4d80502b6

View file

@ -4468,6 +4468,7 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
JSShapeProperty *pr; JSShapeProperty *pr;
void *sh_alloc; void *sh_alloc;
intptr_t h; intptr_t h;
JSShape *old_sh;
sh = *psh; sh = *psh;
new_size = max_int(count, sh->prop_size * 3 / 2); new_size = max_int(count, sh->prop_size * 3 / 2);
@ -4483,19 +4484,21 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
new_hash_size = sh->prop_hash_mask + 1; new_hash_size = sh->prop_hash_mask + 1;
while (new_hash_size < new_size) while (new_hash_size < new_size)
new_hash_size = 2 * new_hash_size; new_hash_size = 2 * new_hash_size;
if (new_hash_size != (sh->prop_hash_mask + 1)) { /* resize the property shapes. Using js_realloc() is not possible in
JSShape *old_sh; case the GC runs during the allocation */
/* resize the hash table and the properties */
old_sh = sh; old_sh = sh;
sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size)); sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
if (!sh_alloc) if (!sh_alloc)
return -1; return -1;
sh = get_shape_from_alloc(sh_alloc, new_hash_size); sh = get_shape_from_alloc(sh_alloc, new_hash_size);
list_del(&old_sh->header.link); list_del(&old_sh->header.link);
/* copy all the fields and the properties */ /* copy all the shape properties */
memcpy(sh, old_sh, memcpy(sh, old_sh,
sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count); sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
if (new_hash_size != (sh->prop_hash_mask + 1)) {
/* resize the hash table and the properties */
new_hash_mask = new_hash_size - 1; new_hash_mask = new_hash_size - 1;
sh->prop_hash_mask = new_hash_mask; sh->prop_hash_mask = new_hash_mask;
memset(prop_hash_end(sh) - new_hash_size, 0, memset(prop_hash_end(sh) - new_hash_size, 0,
@ -4507,20 +4510,12 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
prop_hash_end(sh)[-h - 1] = i + 1; prop_hash_end(sh)[-h - 1] = i + 1;
} }
} }
js_free(ctx, get_alloc_from_shape(old_sh));
} else { } else {
/* only resize the properties */ /* just copy the previous hash table */
list_del(&sh->header.link); memcpy(prop_hash_end(sh) - new_hash_size, prop_hash_end(old_sh) - new_hash_size,
sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh), sizeof(prop_hash_end(sh)[0]) * new_hash_size);
get_shape_size(new_hash_size, new_size));
if (unlikely(!sh_alloc)) {
/* insert again in the GC list */
list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
return -1;
}
sh = get_shape_from_alloc(sh_alloc, new_hash_size);
list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
} }
js_free(ctx, get_alloc_from_shape(old_sh));
*psh = sh; *psh = sh;
sh->prop_size = new_size; sh->prop_size = new_size;
return 0; return 0;