diff options
author | Peter Zhu <peter@peterzhu.ca> | 2023-02-28 14:59:33 -0500 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2023-03-03 16:12:03 -0500 |
commit | 62c2082f1f726cb90d8c332fbedbecf41d5d82ec (patch) | |
tree | f768c3103ed1ad0d0e1fa3ab00a253af08cd6e79 /vm_insnhelper.c | |
parent | 0700d0fd1c77b4fddf803dea3c10be654df600ff (diff) | |
download | ruby-62c2082f1f726cb90d8c332fbedbecf41d5d82ec.tar.gz |
[Bug #19469] Fix crash when resizing generic iv list
The following script can sometimes trigger a crash:
```ruby
GC.stress = true
class Array
def foo(bool)
if bool
@a = 1
@b = 2
@c = 1
else
@c = 1
end
end
end
obj = []
obj.foo(true)
obj2 = []
obj2.foo(false)
obj3 = []
obj3.foo(true)
```
This is because vm_setivar_default calls rb_ensure_generic_iv_list_size
to resize the iv list. However, the call to gen_ivtbl_resize reallocs
the iv list, and then inserts into the generic iv table. If the
st_insert triggers a GC then the old iv list will be read during
marking, causing a use-after-free bug.
Co-Authored-By: Jemma Issroff <jemmaissroff@gmail.com>
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c index e0d227990b..a43f6ef94d 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1416,11 +1416,11 @@ vm_setivar_default(VALUE obj, ID id, VALUE val, shape_id_t dest_shape_id, attr_i shape_id_t source_shape_id = dest_shape->parent_id; if (shape_id == source_shape_id && dest_shape->edge_name == id && dest_shape->type == SHAPE_IVAR) { - ivtbl = rb_ensure_generic_iv_list_size(obj, index + 1); + ivtbl = rb_ensure_generic_iv_list_size(obj, dest_shape, index + 1); #if SHAPE_IN_BASIC_FLAGS RBASIC_SET_SHAPE_ID(obj, dest_shape_id); #else - ivtbl->shape_id = dest_shape_id; + RUBY_ASSERT(ivtbl->shape_id == dest_shape_id); #endif } else { |