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

ruby-changes:50545

From: nobu <ko1@a...>
Date: Wed, 7 Mar 2018 17:07:29 +0900 (JST)
Subject: [ruby-changes:50545] nobu:r62685 (trunk): date_core.c: check conversion

nobu	2018-03-07 17:07:24 +0900 (Wed, 07 Mar 2018)

  New Revision: 62685

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

  Log:
    date_core.c: check conversion
    
    * ext/date/date_core.c (offset_to_sec, d_lite_plus): check
      conversion results, to get rid of infinite recursion.

  Modified files:
    trunk/ext/date/date_core.c
    trunk/test/date/test_date_arith.rb
Index: ext/date/date_core.c
===================================================================
--- ext/date/date_core.c	(revision 62684)
+++ ext/date/date_core.c	(revision 62685)
@@ -2333,6 +2333,9 @@ VALUE date_zone_to_diff(VALUE); https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L2333
 static int
 offset_to_sec(VALUE vof, int *rof)
 {
+    int try_rational = 1;
+
+  again:
     switch (TYPE(vof)) {
       case T_FIXNUM:
 	{
@@ -2359,10 +2362,11 @@ offset_to_sec(VALUE vof, int *rof) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L2362
       default:
 	expect_numeric(vof);
 	vof = f_to_r(vof);
-#ifdef CANONICALIZATION_FOR_MATHN
-	if (!k_rational_p(vof))
-	    return offset_to_sec(vof, rof);
-#endif
+	if (!k_rational_p(vof)) {
+	    if (!try_rational) Check_Type(vof, T_RATIONAL);
+	    try_rational = 0;
+	    goto again;
+	}
 	/* fall through */
       case T_RATIONAL:
 	{
@@ -2371,17 +2375,10 @@ offset_to_sec(VALUE vof, int *rof) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L2375
 
 	    vs = day_to_sec(vof);
 
-#ifdef CANONICALIZATION_FOR_MATHN
 	    if (!k_rational_p(vs)) {
-		if (!FIXNUM_P(vs))
-		    return 0;
-		n = FIX2LONG(vs);
-		if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
-		    return 0;
-		*rof = (int)n;
-		return 1;
+		vn = vs;
+		goto rounded;
 	    }
-#endif
 	    vn = rb_rational_num(vs);
 	    vd = rb_rational_den(vs);
 
@@ -2391,6 +2388,7 @@ offset_to_sec(VALUE vof, int *rof) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L2388
 		vn = f_round(vs);
 		if (!f_eqeq_p(vn, vs))
 		    rb_warning("fraction of offset is ignored");
+	      rounded:
 		if (!FIXNUM_P(vn))
 		    return 0;
 		n = FIX2LONG(vn);
@@ -5513,8 +5511,10 @@ d_lite_new_offset(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L5511
 static VALUE
 d_lite_plus(VALUE self, VALUE other)
 {
+    int try_rational = 1;
     get_d1(self);
 
+  again:
     switch (TYPE(other)) {
       case T_FIXNUM:
 	{
@@ -5724,18 +5724,21 @@ d_lite_plus(VALUE self, VALUE other) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L5724
       default:
 	expect_numeric(other);
 	other = f_to_r(other);
-#ifdef CANONICALIZATION_FOR_MATHN
-	if (!k_rational_p(other))
-	    return d_lite_plus(self, other);
-#endif
+	if (!k_rational_p(other)) {
+	    if (!try_rational) Check_Type(other, T_RATIONAL);
+	    try_rational = 0;
+	    goto again;
+	}
 	/* fall through */
       case T_RATIONAL:
 	{
 	    VALUE nth, sf, t;
 	    int jd, df, s;
 
-	    if (wholenum_p(other))
-		return d_lite_plus(self, rb_rational_num(other));
+	    if (wholenum_p(other)) {
+		other = rb_rational_num(other);
+		goto again;
+	    }
 
 	    if (f_positive_p(other))
 		s = +1;
Index: test/date/test_date_arith.rb
===================================================================
--- test/date/test_date_arith.rb	(revision 62684)
+++ test/date/test_date_arith.rb	(revision 62685)
@@ -3,11 +3,18 @@ require 'test/unit' https://github.com/ruby/ruby/blob/trunk/test/date/test_date_arith.rb#L3
 require 'date'
 
 class TestDateArith < Test::Unit::TestCase
+  class Rat < Numeric
+    def to_r; self; end
+  end
 
   def test_new_offset
     d = DateTime.new(2002, 3, 14)
     assert_equal(Rational(9, 24), d.new_offset(Rational(9, 24)).offset)
     assert_equal(Rational(9, 24), d.new_offset('+0900').offset)
+    n = Rat.new
+    assert_raise(TypeError) do
+      Timeout.timeout(1) {d.new_offset(n)}
+    end
   end
 
   def test__plus
@@ -37,6 +44,13 @@ class TestDateArith < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/test/date/test_date_arith.rb#L44
     assert_raise(e) do
       DateTime.new(2000,2,29) + Time.mktime(2000,2,29)
     end
+    n = Rat.new
+    assert_raise(e) do
+      Timeout.timeout(1) {Date.new(2000,2,29) + n}
+    end
+    assert_raise(e) do
+      Timeout.timeout(1) {DateTime.new(2000,2,29) + n}
+    end
   end
 
   def test__minus

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

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