зеркало из https://github.com/github/ruby.git
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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62685 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
7a363dd91f
Коммит
7ab3f98604
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче