diff --git a/hash.c b/hash.c index 007508a..b4d650a 100644 --- a/hash.c +++ b/hash.c @@ -667,13 +667,19 @@ rb_hash_rehash(VALUE hash) } static VALUE +ifnone_recursive(VALUE obj, VALUE arg, int recurse) { + if (recurse) return Qnil; + return rb_funcall(RHASH_IFNONE(obj), id_yield, 2, obj, arg); +} + +static VALUE hash_default_value(VALUE hash, VALUE key) { if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { VALUE ifnone = RHASH_IFNONE(hash); if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone; if (key == Qundef) return Qnil; - return rb_funcall(ifnone, id_yield, 2, hash, key); + return rb_exec_recursive_paired_outer(ifnone_recursive, hash, key, key); } else { return rb_funcall(hash, id_default, 1, key); diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index 7cf5b8a..a63f769 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -810,6 +810,14 @@ class TestHash < Test::Unit::TestCase assert_equal(true, h[:nope]) h = @cls[] assert_nil(h.default_proc) + + bug9683 = '[Bug #9683]' + h = @cls.new {|hh, k| hh[k] += 1 } + assert_nothing_raised(SystemStackError, bug9683) { h[1] } + + fac = @cls.new {|hh, k| hh[k] = hh[k-1]*k } + fac[1] = 1 + assert_nothing_raised(SystemStackError, bug9683) { fac[5] } end def test_shift2