[前][次][番号順一覧][スレッド一覧]

ruby-changes:31780

From: nobu <ko1@a...>
Date: Tue, 26 Nov 2013 22:43:46 +0900 (JST)
Subject: [ruby-changes:31780] nobu:r43859 (trunk): hash.c: cut off if recursion

nobu	2013-11-26 22:43:40 +0900 (Tue, 26 Nov 2013)

  New Revision: 43859

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43859

  Log:
    hash.c: cut off if recursion
    
    * hash.c (rb_hash): cut off if recursion detected to get rid of stack
      overflow.  [ruby-core:58567] [Bug #9151]

  Modified files:
    trunk/ChangeLog
    trunk/hash.c
    trunk/test/ruby/test_hash.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43858)
+++ ChangeLog	(revision 43859)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Nov 26 22:43:36 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* hash.c (rb_hash): cut off if recursion detected to get rid of stack
+	  overflow.  [ruby-core:58567] [Bug #9151]
+
 Tue Nov 26 20:02:39 2013  Koichi Sasada  <ko1@a...>
 
 	* test/ruby/test_settracefunc.rb: add tests for a_call/a_return
Index: hash.c
===================================================================
--- hash.c	(revision 43858)
+++ hash.c	(revision 43859)
@@ -76,10 +76,17 @@ rb_any_cmp(VALUE a, VALUE b) https://github.com/ruby/ruby/blob/trunk/hash.c#L76
     return !rb_eql(a, b);
 }
 
+static VALUE
+hash_recursive(VALUE obj, VALUE arg, int recurse)
+{
+    if (recurse) return INT2FIX(0);
+    return rb_funcallv(obj, id_hash, 0, 0);
+}
+
 VALUE
 rb_hash(VALUE obj)
 {
-    VALUE hval = rb_funcall(obj, id_hash, 0);
+    VALUE hval = rb_exec_recursive(hash_recursive, obj, 0);
   retry:
     switch (TYPE(hval)) {
       case T_FIXNUM:
Index: test/ruby/test_hash.rb
===================================================================
--- test/ruby/test_hash.rb	(revision 43858)
+++ test/ruby/test_hash.rb	(revision 43859)
@@ -1060,6 +1060,20 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1060
     end
   end
 
+  def test_recursive_hash_value
+    bug9151 = '[ruby-core:58567] [Bug #9151]'
+
+    s = Struct.new(:x) {def hash; [x,""].hash; end}
+    a = s.new
+    b = s.new
+    a.x = b
+    b.x = a
+    ah = assert_nothing_raised(SystemStackError, bug9151) {a.hash}
+    bh = assert_nothing_raised(SystemStackError, bug9151) {b.hash}
+    assert_equal(ah, bh, bug9151)
+    assert_not_equal([a,"hello"].hash, [b,"world"].hash, bug9151)
+  end
+
   class TestSubHash < TestHash
     class SubHash < Hash
     end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]