mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 12:34:21 +00:00
Free after insert in generic_ivar_set_shape_fields
Previously we were performing a realloc and then inserting the new value into the table. If the table was flagged as requiring a rebuild, this could trigger GC work and marking within that GC could access the fields freed by realloc.
This commit is contained in:
parent
8aac19d598
commit
055fef00a1
Notes:
git
2025-06-17 06:01:35 +00:00
29
variable.c
29
variable.c
@ -1227,12 +1227,6 @@ gen_fields_tbl_bytes(size_t n)
|
||||
return offsetof(struct gen_fields_tbl, as.shape.fields) + n * sizeof(VALUE);
|
||||
}
|
||||
|
||||
static struct gen_fields_tbl *
|
||||
gen_fields_tbl_resize(struct gen_fields_tbl *old, uint32_t new_capa)
|
||||
{
|
||||
RUBY_ASSERT(new_capa > 0);
|
||||
return xrealloc(old, gen_fields_tbl_bytes(new_capa));
|
||||
}
|
||||
|
||||
void
|
||||
rb_mark_generic_ivar(VALUE obj)
|
||||
@ -1837,13 +1831,28 @@ generic_ivar_set_shape_fields(VALUE obj, void *data)
|
||||
int existing = st_lookup(tbl, (st_data_t)obj, (st_data_t *)&fields_tbl);
|
||||
|
||||
if (!existing || fields_lookup->resize) {
|
||||
uint32_t new_capa = RSHAPE_CAPACITY(fields_lookup->shape_id);
|
||||
uint32_t old_capa = RSHAPE_CAPACITY(RSHAPE_PARENT(fields_lookup->shape_id));
|
||||
|
||||
if (existing) {
|
||||
RUBY_ASSERT(RSHAPE_TYPE_P(fields_lookup->shape_id, SHAPE_IVAR) || RSHAPE_TYPE_P(fields_lookup->shape_id, SHAPE_OBJ_ID));
|
||||
RUBY_ASSERT(RSHAPE_CAPACITY(RSHAPE_PARENT(fields_lookup->shape_id)) < RSHAPE_CAPACITY(fields_lookup->shape_id));
|
||||
RUBY_ASSERT(old_capa < new_capa);
|
||||
RUBY_ASSERT(fields_tbl);
|
||||
} else {
|
||||
RUBY_ASSERT(!fields_tbl);
|
||||
RUBY_ASSERT(old_capa == 0);
|
||||
}
|
||||
RUBY_ASSERT(new_capa > 0);
|
||||
|
||||
fields_tbl = gen_fields_tbl_resize(fields_tbl, RSHAPE_CAPACITY(fields_lookup->shape_id));
|
||||
struct gen_fields_tbl *old_fields_tbl = fields_tbl;
|
||||
fields_tbl = xmalloc(gen_fields_tbl_bytes(new_capa));
|
||||
if (old_fields_tbl) {
|
||||
memcpy(fields_tbl, old_fields_tbl, gen_fields_tbl_bytes(old_capa));
|
||||
}
|
||||
st_insert(tbl, (st_data_t)obj, (st_data_t)fields_tbl);
|
||||
if (old_fields_tbl) {
|
||||
xfree(old_fields_tbl);
|
||||
}
|
||||
}
|
||||
|
||||
if (fields_lookup->shape_id) {
|
||||
@ -2371,7 +2380,9 @@ rb_copy_generic_ivar(VALUE dest, VALUE obj)
|
||||
return;
|
||||
}
|
||||
|
||||
new_fields_tbl = gen_fields_tbl_resize(0, RSHAPE_CAPACITY(dest_shape_id));
|
||||
uint32_t dest_capa = RSHAPE_CAPACITY(dest_shape_id);
|
||||
RUBY_ASSERT(dest_capa > 0);
|
||||
new_fields_tbl = xmalloc(gen_fields_tbl_bytes(dest_capa));
|
||||
|
||||
VALUE *src_buf = obj_fields_tbl->as.shape.fields;
|
||||
VALUE *dest_buf = new_fields_tbl->as.shape.fields;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user