diff options
author | Peter Zhu <peter@peterzhu.ca> | 2022-12-19 11:21:16 -0500 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2022-12-19 13:13:26 -0500 |
commit | 8275cad1e1646a2b301962313dc3e8ff1deb87b3 (patch) | |
tree | a4ceda3cf6b87f5078c01841c3eea9ac4829f8ec | |
parent | b2f53dccbedd9f399bc4668eb02f26b2eafa6f5c (diff) | |
download | ruby-8275cad1e1646a2b301962313dc3e8ff1deb87b3.tar.gz |
Fix buffer overrun when re-embedding objects
We eagerly set the new shape of an object when moving an object during
compaction. This new shape may have a different capacity than the
current original shape capacity. This means that we cannot copy from the
original buffer using size of the new capacity. Instead, we should use
the ivar count (which is less than or equal to both the new and original
capacities).
Co-Authored-By: Matt Valentine-House <matt@eightbitraptor.com>
-rw-r--r-- | gc.c | 6 |
1 files changed, 2 insertions, 4 deletions
@@ -10118,13 +10118,11 @@ gc_ref_update_object(rb_objspace_t *objspace, VALUE v) } #if USE_RVARGC - uint32_t numiv = ROBJECT_IV_CAPACITY(v); - size_t slot_size = rb_gc_obj_slot_size(v); - size_t embed_size = rb_obj_embedded_size(numiv); + size_t embed_size = rb_obj_embedded_size(ROBJECT_IV_CAPACITY(v)); if (slot_size >= embed_size && !RB_FL_TEST_RAW(v, ROBJECT_EMBED)) { // Object can be re-embedded - memcpy(ROBJECT(v)->as.ary, ptr, sizeof(VALUE) * numiv); + memcpy(ROBJECT(v)->as.ary, ptr, sizeof(VALUE) * ROBJECT_IV_COUNT(v)); RB_FL_SET_RAW(v, ROBJECT_EMBED); if (ROBJ_TRANSIENT_P(v)) { ROBJ_TRANSIENT_UNSET(v); |