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

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62685 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-03-07 08:07:24 +00:00
Родитель 7a363dd91f
Коммит 7ab3f98604
2 изменённых файлов: 36 добавлений и 19 удалений

Просмотреть файл

@ -2333,6 +2333,9 @@ VALUE date_zone_to_diff(VALUE);
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)
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)
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)
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, VALUE self)
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)
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;

Просмотреть файл

@ -3,11 +3,18 @@ require 'test/unit'
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::TestCase
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