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
This commit is contained in:
Peter Zhu 2022-11-14 10:24:55 -05:00
parent 36dc99af5a
commit 5dcbe58833
Notes: git 2022-11-15 13:54:15 +00:00

View File

@ -342,7 +342,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);
}