Skip to content

Commit 94f01c5

Browse files
committed
should not ignore the rest of recursive constructs
* array.c (rb_ary_hash): should not ignore the rest of recursive constructs. * hash.c (rb_hash_hash): ditto. * range.c (range_hash): ditto. * struct.c (rb_struct_hash): ditto. * test/-ext-/test_recursion.rb (TestRecursion): separate from test/ruby/test_thread.rb. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43860 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent d503381 commit 94f01c5

File tree

10 files changed

+85
-18
lines changed

10 files changed

+85
-18
lines changed

ChangeLog

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
Wed Nov 27 02:20:13 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
2+
3+
* array.c (rb_ary_hash): should not ignore the rest of recursive
4+
constructs.
5+
6+
* hash.c (rb_hash_hash): ditto.
7+
8+
* range.c (range_hash): ditto.
9+
10+
* struct.c (rb_struct_hash): ditto.
11+
12+
* test/-ext-/test_recursion.rb (TestRecursion): separate from
13+
test/ruby/test_thread.rb.
14+
115
Tue Nov 26 22:43:36 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
216

317
* hash.c (rb_hash): cut off if recursion detected to get rid of stack

array.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3807,7 +3807,7 @@ recursive_hash(VALUE ary, VALUE dummy, int recur)
38073807
static VALUE
38083808
rb_ary_hash(VALUE ary)
38093809
{
3810-
return rb_exec_recursive_outer(recursive_hash, ary, 0);
3810+
return rb_exec_recursive_paired(recursive_hash, ary, ary, 0);
38113811
}
38123812

38133813
/*

ext/-test-/recursion/extconf.rb

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require 'mkmf'
2+
create_makefile("-test-/recursion")

ext/-test-/recursion/recursion.c

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <ruby.h>
2+
3+
static VALUE
4+
recursive_i(VALUE obj, VALUE mid, int recur)
5+
{
6+
if (recur) return Qnil;
7+
return rb_funcallv(obj, rb_to_id(mid), 0, 0);
8+
}
9+
10+
static VALUE
11+
exec_recursive(VALUE self, VALUE mid)
12+
{
13+
return rb_exec_recursive(recursive_i, self, mid);
14+
}
15+
16+
static VALUE
17+
exec_recursive_outer(VALUE self, VALUE mid)
18+
{
19+
return rb_exec_recursive_outer(recursive_i, self, mid);
20+
}
21+
22+
void
23+
Init_recursion(void)
24+
{
25+
VALUE m = rb_define_module_under(rb_define_module("Bug"), "Recursive");
26+
rb_define_method(m, "exec_recursive", exec_recursive, 1);
27+
rb_define_method(m, "exec_recursive_outer", exec_recursive_outer, 1);
28+
}

hash.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1944,7 +1944,7 @@ recursive_hash(VALUE hash, VALUE dummy, int recur)
19441944
static VALUE
19451945
rb_hash_hash(VALUE hash)
19461946
{
1947-
return rb_exec_recursive_outer(recursive_hash, hash, 0);
1947+
return rb_exec_recursive_paired(recursive_hash, hash, hash, 0);
19481948
}
19491949

19501950
static int

range.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ recursive_hash(VALUE range, VALUE dummy, int recur)
274274
static VALUE
275275
range_hash(VALUE range)
276276
{
277-
return rb_exec_recursive_outer(recursive_hash, range, 0);
277+
return rb_exec_recursive_paired(recursive_hash, range, range, 0);
278278
}
279279

280280
static void

struct.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ recursive_hash(VALUE s, VALUE dummy, int recur)
980980
static VALUE
981981
rb_struct_hash(VALUE s)
982982
{
983-
return rb_exec_recursive_outer(recursive_hash, s, 0);
983+
return rb_exec_recursive_paired(recursive_hash, s, s, 0);
984984
}
985985

986986
static VALUE

test/-ext-/test_recursion.rb

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- coding: us-ascii -*-
2+
require 'test/unit'
3+
require_relative '../ruby/envutil'
4+
5+
class TestRecursion < Test::Unit::TestCase
6+
require '-test-/recursion'
7+
8+
def setup
9+
@obj = Struct.new(:visited).new(false)
10+
@obj.extend(Bug::Recursive)
11+
end
12+
13+
def test_recursive
14+
def @obj.doit
15+
self.visited = true
16+
exec_recursive(:doit)
17+
raise "recursive"
18+
end
19+
assert_raise_with_message(RuntimeError, "recursive") {
20+
@obj.exec_recursive(:doit)
21+
}
22+
assert(@obj.visited, "obj.hash was not called")
23+
end
24+
25+
def test_recursive_outer
26+
def @obj.doit
27+
self.visited = true
28+
exec_recursive_outer(:doit)
29+
raise "recursive_outer should short circuit intermediate calls"
30+
end
31+
assert_nothing_raised {
32+
@obj.exec_recursive_outer(:doit)
33+
}
34+
assert(@obj.visited, "obj.hash was not called")
35+
end
36+
end

test/ruby/test_array.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -2012,9 +2012,9 @@ def o.==(o)
20122012
end
20132013

20142014
def test_hash2
2015+
assert_not_equal([[1]].hash, [[2]].hash)
20152016
a = []
20162017
a << a
2017-
assert_equal([[a]].hash, a.hash)
20182018
assert_not_equal([a, a].hash, a.hash) # Implementation dependent
20192019
end
20202020

test/ruby/test_thread.rb

-13
Original file line numberDiff line numberDiff line change
@@ -467,19 +467,6 @@ def test_mutex_trylock
467467
m.unlock
468468
end
469469

470-
def test_recursive_outer
471-
arr = []
472-
obj = Struct.new(:foo, :visited).new(arr, false)
473-
arr << obj
474-
def obj.hash
475-
self[:visited] = true
476-
super
477-
raise "recursive_outer should short circuit intermediate calls"
478-
end
479-
assert_nothing_raised {arr.hash}
480-
assert(obj[:visited], "obj.hash was not called")
481-
end
482-
483470
def test_thread_instance_variable
484471
bug4389 = '[ruby-core:35192]'
485472
assert_in_out_err([], <<-INPUT, %w(), [], bug4389)

0 commit comments

Comments
 (0)