diff options
author | Kazuki Tsujimoto <kazuki@callcc.net> | 2019-11-19 09:35:47 -0600 |
---|---|---|
committer | Kazuki Tsujimoto <kazuki@callcc.net> | 2019-11-19 15:35:14 -0600 |
commit | ff41663403d3eb76d95f465cb94e14d2faaa04d1 (patch) | |
tree | 28f984be774837a41fd277319a8b2dc12c0501d5 | |
parent | 61131edba7c885a6d12c4d6f0e502fb40381f184 (diff) | |
download | ruby-ff41663403d3eb76d95f465cb94e14d2faaa04d1.tar.gz |
Fix memory corruption in Enumerable#reverse_each [ruby-dev:50867] [Bug #16354]
-rw-r--r-- | enum.c | 12 | ||||
-rw-r--r-- | test/ruby/test_enum.rb | 13 |
2 files changed, 22 insertions, 3 deletions
@@ -2419,14 +2419,20 @@ static VALUE enum_reverse_each(int argc, VALUE *argv, VALUE obj) { VALUE ary; - long i; + long len; RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size); ary = enum_to_a(argc, argv, obj); - for (i = RARRAY_LEN(ary); --i >= 0; ) { - rb_yield(RARRAY_AREF(ary, i)); + len = RARRAY_LEN(ary); + while (len--) { + long nlen; + rb_yield(RARRAY_AREF(ary, len)); + nlen = RARRAY_LEN(ary); + if (nlen < len) { + len = nlen; + } } return obj; diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb index 5fbb2d3663..7b647231c8 100644 --- a/test/ruby/test_enum.rb +++ b/test/ruby/test_enum.rb @@ -735,6 +735,19 @@ class TestEnumerable < Test::Unit::TestCase assert_equal([2,1,3,2,1], @obj.reverse_each.to_a) end + def test_reverse_each_memory_corruption + bug16354 = '[ruby-dev:50867]' + assert_normal_exit %q{ + size = 1000 + (0...size).reverse_each do |i| + i.inspect + ObjectSpace.each_object(Array) do |a| + a.clear if a.length == size + end + end + }, bug16354 + end + def test_chunk e = [].chunk {|elt| true } assert_equal([], e.to_a) |