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

ruby-changes:46856

From: nobu <ko1@a...>
Date: Tue, 30 May 2017 22:12:27 +0900 (JST)
Subject: [ruby-changes:46856] nobu:r58971 (trunk): enum.c: check if reentered

nobu	2017-05-30 22:12:22 +0900 (Tue, 30 May 2017)

  New Revision: 58971

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=58971

  Log:
    enum.c: check if reentered
    
    * enum.c (cmpint_reenter_check): extract from nmin_cmp and
      nmin_block_cmp.
    
    * enum.c (nmin_cmp): check if reentered before rb_cmpint.
      [Feature #13437]

  Modified files:
    trunk/enum.c
    trunk/test/ruby/test_enum.rb
Index: enum.c
===================================================================
--- enum.c	(revision 58970)
+++ enum.c	(revision 58971)
@@ -1263,16 +1263,24 @@ struct nmin_data { https://github.com/ruby/ruby/blob/trunk/enum.c#L1263
   const char *method;
 };
 
+static VALUE
+cmpint_reenter_check(struct nmin_data *data, VALUE val)
+{
+    if (RBASIC(data->buf)->klass) {
+	rb_raise(rb_eRuntimeError, "%s reentered", data->method);
+    }
+    return val;
+}
+
 static int
 nmin_cmp(const void *ap, const void *bp, void *_data)
 {
     struct cmp_opt_data cmp_opt = { 0, 0 };
     struct nmin_data *data = (struct nmin_data *)_data;
     VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
-    if (RBASIC(data->buf)->klass) {
-	rb_raise(rb_eRuntimeError, "%s reentered", data->method);
-    }
+#define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
     return OPTIMIZED_CMP(a, b, cmp_opt);
+#undef rb_cmpint
 }
 
 static int
@@ -1281,13 +1289,10 @@ nmin_block_cmp(const void *ap, const voi https://github.com/ruby/ruby/blob/trunk/enum.c#L1289
     struct nmin_data *data = (struct nmin_data *)_data;
     VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
     VALUE cmp = rb_yield_values(2, a, b);
-    if (RBASIC(data->buf)->klass) {
-	rb_raise(rb_eRuntimeError, "%s reentered", data->method);
-    }
+    cmpint_reenter_check(data, cmp);
     return rb_cmpint(cmp, a, b);
 }
 
-
 static void
 nmin_filter(struct nmin_data *data)
 {
Index: test/ruby/test_enum.rb
===================================================================
--- test/ruby/test_enum.rb	(revision 58970)
+++ test/ruby/test_enum.rb	(revision 58971)
@@ -604,6 +604,22 @@ class TestEnumerable < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enum.rb#L604
       [o, o, o].sort_by {|x| x }
       c.call
     end
+
+    assert_raise_with_message(RuntimeError, /reentered/) do
+      i = 0
+      c = nil
+      o = Object.new
+      class << o; self; end.class_eval do
+        define_method(:<=>) do |x|
+          callcc {|c2| c ||= c2 }
+          i += 1
+          0
+        end
+      end
+      [o, o].min(1)
+      assert_operator(i, :<=, 5, "infinite loop")
+      c.call
+    end
   end
 
   def test_reverse_each

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

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