aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-12-20 05:26:08 +0000
committerrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-12-20 05:26:08 +0000
commit185efc2c98bd3d19230067ccb408dbd3bf03f982 (patch)
treea233c4258ad27cda9d4fd0b7157dc43cd4220f31
parent0c44fc2bc0b9bcac022effce53f7fcb7f1bb5af2 (diff)
downloadruby-185efc2c98bd3d19230067ccb408dbd3bf03f982.tar.gz
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/trunk@57119 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--array.c4
-rw-r--r--test/ruby/test_array.rb13
2 files changed, 12 insertions, 5 deletions
diff --git a/array.c b/array.c
index 0fa3494dcd..b7ef04f397 100644
--- a/array.c
+++ b/array.c
@@ -5194,7 +5194,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)));
}
}
@@ -5393,7 +5393,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 6ac2ff1c80..563a37ee2e 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -2483,11 +2483,18 @@ class TestArray < Test::Unit::TestCase
def test_combination_clear
bug9939 = '[ruby-core:63149] [Bug #9939]'
- assert_ruby_status([], <<-'end;', bug9939)
- 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