Skip to content

Commit 055fef0

Browse files
jhawthornbyroot
authored andcommitted
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.
1 parent 8aac19d commit 055fef0

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

variable.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,12 +1227,6 @@ gen_fields_tbl_bytes(size_t n)
12271227
return offsetof(struct gen_fields_tbl, as.shape.fields) + n * sizeof(VALUE);
12281228
}
12291229

1230-
static struct gen_fields_tbl *
1231-
gen_fields_tbl_resize(struct gen_fields_tbl *old, uint32_t new_capa)
1232-
{
1233-
RUBY_ASSERT(new_capa > 0);
1234-
return xrealloc(old, gen_fields_tbl_bytes(new_capa));
1235-
}
12361230

12371231
void
12381232
rb_mark_generic_ivar(VALUE obj)
@@ -1837,13 +1831,28 @@ generic_ivar_set_shape_fields(VALUE obj, void *data)
18371831
int existing = st_lookup(tbl, (st_data_t)obj, (st_data_t *)&fields_tbl);
18381832

18391833
if (!existing || fields_lookup->resize) {
1834+
uint32_t new_capa = RSHAPE_CAPACITY(fields_lookup->shape_id);
1835+
uint32_t old_capa = RSHAPE_CAPACITY(RSHAPE_PARENT(fields_lookup->shape_id));
1836+
18401837
if (existing) {
18411838
RUBY_ASSERT(RSHAPE_TYPE_P(fields_lookup->shape_id, SHAPE_IVAR) || RSHAPE_TYPE_P(fields_lookup->shape_id, SHAPE_OBJ_ID));
1842-
RUBY_ASSERT(RSHAPE_CAPACITY(RSHAPE_PARENT(fields_lookup->shape_id)) < RSHAPE_CAPACITY(fields_lookup->shape_id));
1839+
RUBY_ASSERT(old_capa < new_capa);
1840+
RUBY_ASSERT(fields_tbl);
1841+
} else {
1842+
RUBY_ASSERT(!fields_tbl);
1843+
RUBY_ASSERT(old_capa == 0);
18431844
}
1845+
RUBY_ASSERT(new_capa > 0);
18441846

1845-
fields_tbl = gen_fields_tbl_resize(fields_tbl, RSHAPE_CAPACITY(fields_lookup->shape_id));
1847+
struct gen_fields_tbl *old_fields_tbl = fields_tbl;
1848+
fields_tbl = xmalloc(gen_fields_tbl_bytes(new_capa));
1849+
if (old_fields_tbl) {
1850+
memcpy(fields_tbl, old_fields_tbl, gen_fields_tbl_bytes(old_capa));
1851+
}
18461852
st_insert(tbl, (st_data_t)obj, (st_data_t)fields_tbl);
1853+
if (old_fields_tbl) {
1854+
xfree(old_fields_tbl);
1855+
}
18471856
}
18481857

18491858
if (fields_lookup->shape_id) {
@@ -2371,7 +2380,9 @@ rb_copy_generic_ivar(VALUE dest, VALUE obj)
23712380
return;
23722381
}
23732382

2374-
new_fields_tbl = gen_fields_tbl_resize(0, RSHAPE_CAPACITY(dest_shape_id));
2383+
uint32_t dest_capa = RSHAPE_CAPACITY(dest_shape_id);
2384+
RUBY_ASSERT(dest_capa > 0);
2385+
new_fields_tbl = xmalloc(gen_fields_tbl_bytes(dest_capa));
23752386

23762387
VALUE *src_buf = obj_fields_tbl->as.shape.fields;
23772388
VALUE *dest_buf = new_fields_tbl->as.shape.fields;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy