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

ruby-changes:63414

From: Kenta <ko1@a...>
Date: Thu, 22 Oct 2020 18:00:25 +0900 (JST)
Subject: [ruby-changes:63414] d23d5c3130 (master): rational.c: try converting by to_int in Rational() (#3684)

https://git.ruby-lang.org/ruby.git/commit/?id=d23d5c3130

From d23d5c3130a0944e7e591370cbf8599009318a7c Mon Sep 17 00:00:00 2001
From: Kenta Murata <mrkn@u...>
Date: Thu, 22 Oct 2020 17:59:52 +0900
Subject: rational.c: try converting by to_int in Rational() (#3684)

[Bug #12485]

diff --git a/rational.c b/rational.c
index 6ac42bf..3176870 100644
--- a/rational.c
+++ b/rational.c
@@ -2573,6 +2573,8 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise) https://github.com/ruby/ruby/blob/trunk/rational.c#L2573
     VALUE a1 = numv, a2 = denv;
     int state;
 
+    assert(a1 != Qundef);
+
     if (NIL_P(a1) || NIL_P(a2)) {
         if (!raise) return Qnil;
         rb_raise(rb_eTypeError, "can't convert nil into Rational");
@@ -2588,21 +2590,47 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise) https://github.com/ruby/ruby/blob/trunk/rational.c#L2590
             a2 = RCOMPLEX(a2)->real;
     }
 
-    if (RB_FLOAT_TYPE_P(a1)) {
+    if (RB_INTEGER_TYPE_P(a1)) {
+        // nothing to do
+    }
+    else if (RB_FLOAT_TYPE_P(a1)) {
         a1 = float_to_r(a1);
     }
+    else if (RB_TYPE_P(a1, T_RATIONAL)) {
+        // nothing to do
+    }
     else if (RB_TYPE_P(a1, T_STRING)) {
         a1 = string_to_r_strict(a1, raise);
         if (!raise && NIL_P(a1)) return Qnil;
     }
+    else if (!rb_respond_to(a1, idTo_r)) {
+        VALUE tmp = rb_protect(rb_check_to_int, a1, NULL);
+        rb_set_errinfo(Qnil);
+        if (!NIL_P(tmp)) {
+            a1 = tmp;
+        }
+    }
 
-    if (RB_FLOAT_TYPE_P(a2)) {
+    if (RB_INTEGER_TYPE_P(a2)) {
+        // nothing to do
+    }
+    else if (RB_FLOAT_TYPE_P(a2)) {
         a2 = float_to_r(a2);
     }
+    else if (RB_TYPE_P(a2, T_RATIONAL)) {
+        // nothing to do
+    }
     else if (RB_TYPE_P(a2, T_STRING)) {
         a2 = string_to_r_strict(a2, raise);
         if (!raise && NIL_P(a2)) return Qnil;
     }
+    else if (a2 != Qundef && !rb_respond_to(a2, idTo_r)) {
+        VALUE tmp = rb_protect(rb_check_to_int, a2, NULL);
+        rb_set_errinfo(Qnil);
+        if (!NIL_P(tmp)) {
+            a2 = tmp;
+        }
+    }
 
     if (RB_TYPE_P(a1, T_RATIONAL)) {
         if (a2 == Qundef || (k_exact_one_p(a2)))
@@ -2610,7 +2638,7 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise) https://github.com/ruby/ruby/blob/trunk/rational.c#L2638
     }
 
     if (a2 == Qundef) {
-        if (!k_integer_p(a1)) {
+        if (!RB_INTEGER_TYPE_P(a1)) {
             if (!raise) {
                 VALUE result = rb_protect(to_rational, a1, NULL);
                 rb_set_errinfo(Qnil);
diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb
index 301890b..5bdf5b7 100644
--- a/test/ruby/test_rational.rb
+++ b/test/ruby/test_rational.rb
@@ -128,6 +128,13 @@ class Rational_Test < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_rational.rb#L128
     assert_raise(TypeError){Rational(Object.new, Object.new)}
     assert_raise(TypeError){Rational(1, Object.new)}
 
+    bug12485 = '[ruby-core:75995] [Bug #12485]'
+    o = Object.new
+    def o.to_int; 1; end
+    assert_equal(1, Rational(o, 1), bug12485)
+    assert_equal(1, Rational(1, o), bug12485)
+    assert_equal(1, Rational(o, o), bug12485)
+
     o = Object.new
     def o.to_r; 1/42r; end
     assert_equal(1/42r, Rational(o))
@@ -834,6 +841,18 @@ class Rational_Test < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_rational.rb#L841
       assert_equal(nil, Rational(1, Object.new, exception: false))
     }
 
+    bug12485 = '[ruby-core:75995] [Bug #12485]'
+    assert_nothing_raised(RuntimeError, bug12485) {
+      o = Object.new
+      def o.to_int; raise; end
+      assert_equal(nil, Rational(o, exception: false))
+    }
+    assert_nothing_raised(RuntimeError, bug12485) {
+      o = Object.new
+      def o.to_int; raise; end
+      assert_equal(nil, Rational(1, o, exception: false))
+    }
+
     o = Object.new;
     def o.to_r; raise; end
     assert_nothing_raised(RuntimeError) {
-- 
cgit v0.10.2


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

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