summaryrefslogtreecommitdiff
path: root/quickjs.c
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2023-12-27 18:19:06 +0100
committerFabrice Bellard <fabrice@bellard.org>2023-12-27 18:19:06 +0100
commitb4d80502b6cfa0e107c89a7576116e2cca11d89a (patch)
tree7b325a36ed56111df75f62fa1903a27fe95fba2a /quickjs.c
parent7414e5f67f9a404f3cf91ffa69d0c93bf46d099e (diff)
downloadquickjs-b4d80502b6cfa0e107c89a7576116e2cca11d89a.tar.gz
quickjs-b4d80502b6cfa0e107c89a7576116e2cca11d89a.zip
fixed crash when resizing property shapes in case of OOM (github issue #129)
Diffstat (limited to 'quickjs.c')
-rw-r--r--quickjs.c41
1 files changed, 18 insertions, 23 deletions
diff --git a/quickjs.c b/quickjs.c
index 6fa773e..dc913ab 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -4468,6 +4468,7 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
JSShapeProperty *pr;
void *sh_alloc;
intptr_t h;
+ JSShape *old_sh;
sh = *psh;
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;
while (new_hash_size < new_size)
new_hash_size = 2 * new_hash_size;
+ /* resize the property shapes. Using js_realloc() is not possible in
+ case the GC runs during the allocation */
+ old_sh = sh;
+ sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
+ if (!sh_alloc)
+ return -1;
+ sh = get_shape_from_alloc(sh_alloc, new_hash_size);
+ list_del(&old_sh->header.link);
+ /* copy all the shape properties */
+ memcpy(sh, old_sh,
+ sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
+ list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
+
if (new_hash_size != (sh->prop_hash_mask + 1)) {
- JSShape *old_sh;
/* resize the hash table and the properties */
- old_sh = sh;
- sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
- if (!sh_alloc)
- return -1;
- sh = get_shape_from_alloc(sh_alloc, new_hash_size);
- list_del(&old_sh->header.link);
- /* copy all the fields and the properties */
- memcpy(sh, old_sh,
- sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
new_hash_mask = new_hash_size - 1;
sh->prop_hash_mask = new_hash_mask;
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;
}
}
- js_free(ctx, get_alloc_from_shape(old_sh));
} else {
- /* only resize the properties */
- list_del(&sh->header.link);
- sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh),
- 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);
+ /* just copy the previous hash table */
+ memcpy(prop_hash_end(sh) - new_hash_size, prop_hash_end(old_sh) - new_hash_size,
+ sizeof(prop_hash_end(sh)[0]) * new_hash_size);
}
+ js_free(ctx, get_alloc_from_shape(old_sh));
*psh = sh;
sh->prop_size = new_size;
return 0;