From 310779344157d9776d28dcac044bda3197ce0f02 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 14 Nov 2022 10:24:55 -0500 Subject: [PATCH] Fix buffer overrun in ivars when rebuilding shapes In rb_shape_rebuild_shape, we need to increase the capacity when capacity == next_iv_index since the next ivar will be writing at index next_iv_index. This bug can be reproduced when assertions are turned on and you run the following code: class Foo def initialize @a1 = 1 @a2 = 1 @a3 = 1 @a4 = 1 @a5 = 1 @a6 = 1 @a7 = 1 end def add_ivars @a8 = 1 @a9 = 1 end end class Bar < Foo end foo = Foo.new foo.add_ivars bar = Bar.new GC.start bar.add_ivars bar.clone You will get the following crash: Assertion Failed: object.c:301:rb_obj_copy_ivar:src_num_ivs <= shape_to_set_on_dest->capacity --- shape.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shape.c b/shape.c index b20ac10a14ce81..a18710b13d9f83 100644 --- a/shape.c +++ b/shape.c @@ -352,7 +352,7 @@ rb_shape_rebuild_shape(rb_shape_t * initial_shape, rb_shape_t * dest_shape) switch (dest_shape->type) { case SHAPE_IVAR: - if (midway_shape->capacity < midway_shape->next_iv_index) { + if (midway_shape->capacity <= midway_shape->next_iv_index) { // There isn't enough room to write this IV, so we need to increase the capacity midway_shape = rb_shape_transition_shape_capa(midway_shape, midway_shape->capacity * 2); }