From aa983c4ccb9db02b47d4f4a470a12111644518f4 Mon Sep 17 00:00:00 2001 From: nagachika Date: Mon, 16 Jan 2017 19:46:03 +0000 Subject: [PATCH] merge revision(s) 57119: [Backport #13052] array.c: check array length every time after yielding Since the Array may be modified during rb_yield(), the length before invoking the block can't be trusted. Fix possible out-of-bounds read in Array#combination and Array#repeated_combination. It may better to make a defensive copy of the Array, but for now let's follow what Array#permutation does. [ruby-core:78738] [Bug #13052] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_3@57350 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- array.c | 4 ++-- test/ruby/test_array.rb | 13 ++++++++++--- version.h | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/array.c b/array.c index 729de9c081..9649473f35 100644 --- a/array.c +++ b/array.c @@ -5063,7 +5063,7 @@ rb_ary_combination(VALUE ary, VALUE num) rb_yield(rb_ary_new2(0)); } else if (n == 1) { - for (i = 0; i < len; i++) { + for (i = 0; i < RARRAY_LEN(ary); i++) { rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i))); } } @@ -5262,7 +5262,7 @@ rb_ary_repeated_combination(VALUE ary, VALUE num) rb_yield(rb_ary_new2(0)); } else if (n == 1) { - for (i = 0; i < len; i++) { + for (i = 0; i < RARRAY_LEN(ary); i++) { rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i))); } } diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index f27b8a5724..03e0b22223 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -2419,11 +2419,18 @@ class TestArray < Test::Unit::TestCase def test_combination_clear bug9939 = '[ruby-core:63149] [Bug #9939]' - assert_separately([], <<-'end;') - 100_000.times {Array.new(1000)} + assert_nothing_raised(bug9939) { a = [*0..100] a.combination(3) {|*,x| a.clear} - end; + } + + bug13052 = '[ruby-core:78738] [Bug #13052] Array#combination segfaults if the Array is modified during iteration' + assert_nothing_raised(bug13052) { + a = [*0..100] + a.combination(1) { a.clear } + a = [*0..100] + a.repeated_combination(1) { a.clear } + } end def test_product2 diff --git a/version.h b/version.h index 832286d490..bdef6a33a5 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.3.3" #define RUBY_RELEASE_DATE "2017-01-17" -#define RUBY_PATCHLEVEL 234 +#define RUBY_PATCHLEVEL 235 #define RUBY_RELEASE_YEAR 2017 #define RUBY_RELEASE_MONTH 1