summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--NEWS3
-rw-r--r--array.c6
-rw-r--r--test/ruby/test_array.rb26
4 files changed, 39 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 7af21fec75..10299209ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sun Jan 25 12:04:12 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (flatten): no need to call to_ary method on elements
+ beyond the given level. [ruby-core:67637] [Bug #10748]
+
Sun Jan 25 00:42:24 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/fiddle/win32/libffi.mk.tmpl: assemble without directory prefix.
diff --git a/NEWS b/NEWS
index 6d034b3dc1..13185d19c0 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,9 @@ with all sufficient information, see the ChangeLog file.
no longer changes the receiver array instantly every time the
block is called. [Feature #10714]
+ * Array#flatten and Array#flatten! no longer try to call #to_ary
+ method on elements beyond the given level. [Bug #10748]
+
* IO
* IO#close doesn't raise when the IO object is closed. [Feature #10718]
diff --git a/array.c b/array.c
index e63778e80d..c02ee57132 100644
--- a/array.c
+++ b/array.c
@@ -4387,11 +4387,15 @@ flatten(VALUE ary, int level, int *modified)
while (1) {
while (i < RARRAY_LEN(ary)) {
elt = RARRAY_AREF(ary, i++);
+ if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
+ rb_ary_push(result, elt);
+ continue;
+ }
tmp = rb_check_array_type(elt);
if (RBASIC(result)->klass) {
rb_raise(rb_eRuntimeError, "flatten reentered");
}
- if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
+ if (NIL_P(tmp)) {
rb_ary_push(result, elt);
}
else {
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 2cec70d452..bf14d3dfc9 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -790,6 +790,19 @@ class TestArray < Test::Unit::TestCase
assert_not_same(a8, a9)
end
+ def test_flatten_splat
+ bug10748 = '[ruby-core:67637] [Bug #10748]'
+ o = Object.new
+ o.singleton_class.class_eval do
+ define_method(:to_ary) do
+ raise bug10748
+ end
+ end
+ a = @cls[@cls[o]]
+ assert_raise_with_message(RuntimeError, bug10748) {a.flatten}
+ assert_nothing_raised(RuntimeError, bug10748) {a.flatten(1)}
+ end
+
def test_flatten!
a1 = @cls[ 1, 2, 3]
a2 = @cls[ 5, 6 ]
@@ -814,6 +827,19 @@ class TestArray < Test::Unit::TestCase
assert_nil(@cls[].flatten!(0), '[ruby-core:23382]')
end
+ def test_flatten_splat!
+ bug10748 = '[ruby-core:67637] [Bug #10748]'
+ o = Object.new
+ o.singleton_class.class_eval do
+ define_method(:to_ary) do
+ raise bug10748
+ end
+ end
+ a = @cls[@cls[o]]
+ assert_raise_with_message(RuntimeError, bug10748) {a.flatten!}
+ assert_nothing_raised(RuntimeError, bug10748) {a.flatten!(1)}
+ end
+
def test_flatten_with_callcc
need_continuation
o = Object.new