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/