Fix crash for special constants in too complex generic ivars

We should skip reference updating for entries in too complex generic ivars
that are special constants. This fixes the following crash:

    MAX_SHAPES = 0x80000

    MAX_SHAPES.times do |i|
      o = []
      o.instance_variable_set(:"@foo#{i}", 1)
    end

    o = []

    o.instance_variable_set(:"@a", 123)

    GC.compact
This commit is contained in:
Peter Zhu 2025-02-18 16:26:07 -05:00
parent 27ba268b75
commit 0597cbcb1d
Notes: git 2025-02-18 22:09:45 +00:00
2 changed files with 19 additions and 0 deletions

2
gc.c
View File

@ -3441,6 +3441,8 @@ vm_weak_table_gen_ivar_foreach_too_complex_i(st_data_t _key, st_data_t value, st
GC_ASSERT(!iter_data->weak_only);
if (SPECIAL_CONST_P((VALUE)value)) return ST_CONTINUE;
return iter_data->callback((VALUE)value, iter_data->data);
}

View File

@ -452,4 +452,21 @@ class TestGCCompact < Test::Unit::TestCase
assert_raise(FrozenError) { a.set_a }
end;
end
def test_moving_too_compex_generic_ivar
omit "not compiled with SHAPE_DEBUG" unless defined?(RubyVM::Shape)
assert_separately([], <<~RUBY)
RubyVM::Shape.exhaust_shapes
obj = []
obj.instance_variable_set(:@fixnum, 123)
obj.instance_variable_set(:@str, "hello")
GC.verify_compaction_references(expand_heap: true, toward: :empty)
assert_equal(123, obj.instance_variable_get(:@fixnum))
assert_equal("hello", obj.instance_variable_get(:@str))
RUBY
end
end