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:
parent
7a363dd91f
commit
7ab3f98604
@ -2333,6 +2333,9 @@ VALUE date_zone_to_diff(VALUE);
|
|||||||
static int
|
static int
|
||||||
offset_to_sec(VALUE vof, int *rof)
|
offset_to_sec(VALUE vof, int *rof)
|
||||||
{
|
{
|
||||||
|
int try_rational = 1;
|
||||||
|
|
||||||
|
again:
|
||||||
switch (TYPE(vof)) {
|
switch (TYPE(vof)) {
|
||||||
case T_FIXNUM:
|
case T_FIXNUM:
|
||||||
{
|
{
|
||||||
@ -2359,10 +2362,11 @@ offset_to_sec(VALUE vof, int *rof)
|
|||||||
default:
|
default:
|
||||||
expect_numeric(vof);
|
expect_numeric(vof);
|
||||||
vof = f_to_r(vof);
|
vof = f_to_r(vof);
|
||||||
#ifdef CANONICALIZATION_FOR_MATHN
|
if (!k_rational_p(vof)) {
|
||||||
if (!k_rational_p(vof))
|
if (!try_rational) Check_Type(vof, T_RATIONAL);
|
||||||
return offset_to_sec(vof, rof);
|
try_rational = 0;
|
||||||
#endif
|
goto again;
|
||||||
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case T_RATIONAL:
|
case T_RATIONAL:
|
||||||
{
|
{
|
||||||
@ -2371,17 +2375,10 @@ offset_to_sec(VALUE vof, int *rof)
|
|||||||
|
|
||||||
vs = day_to_sec(vof);
|
vs = day_to_sec(vof);
|
||||||
|
|
||||||
#ifdef CANONICALIZATION_FOR_MATHN
|
|
||||||
if (!k_rational_p(vs)) {
|
if (!k_rational_p(vs)) {
|
||||||
if (!FIXNUM_P(vs))
|
vn = vs;
|
||||||
return 0;
|
goto rounded;
|
||||||
n = FIX2LONG(vs);
|
|
||||||
if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
|
|
||||||
return 0;
|
|
||||||
*rof = (int)n;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
vn = rb_rational_num(vs);
|
vn = rb_rational_num(vs);
|
||||||
vd = rb_rational_den(vs);
|
vd = rb_rational_den(vs);
|
||||||
|
|
||||||
@ -2391,6 +2388,7 @@ offset_to_sec(VALUE vof, int *rof)
|
|||||||
vn = f_round(vs);
|
vn = f_round(vs);
|
||||||
if (!f_eqeq_p(vn, vs))
|
if (!f_eqeq_p(vn, vs))
|
||||||
rb_warning("fraction of offset is ignored");
|
rb_warning("fraction of offset is ignored");
|
||||||
|
rounded:
|
||||||
if (!FIXNUM_P(vn))
|
if (!FIXNUM_P(vn))
|
||||||
return 0;
|
return 0;
|
||||||
n = FIX2LONG(vn);
|
n = FIX2LONG(vn);
|
||||||
@ -5513,8 +5511,10 @@ d_lite_new_offset(int argc, VALUE *argv, VALUE self)
|
|||||||
static VALUE
|
static VALUE
|
||||||
d_lite_plus(VALUE self, VALUE other)
|
d_lite_plus(VALUE self, VALUE other)
|
||||||
{
|
{
|
||||||
|
int try_rational = 1;
|
||||||
get_d1(self);
|
get_d1(self);
|
||||||
|
|
||||||
|
again:
|
||||||
switch (TYPE(other)) {
|
switch (TYPE(other)) {
|
||||||
case T_FIXNUM:
|
case T_FIXNUM:
|
||||||
{
|
{
|
||||||
@ -5724,18 +5724,21 @@ d_lite_plus(VALUE self, VALUE other)
|
|||||||
default:
|
default:
|
||||||
expect_numeric(other);
|
expect_numeric(other);
|
||||||
other = f_to_r(other);
|
other = f_to_r(other);
|
||||||
#ifdef CANONICALIZATION_FOR_MATHN
|
if (!k_rational_p(other)) {
|
||||||
if (!k_rational_p(other))
|
if (!try_rational) Check_Type(other, T_RATIONAL);
|
||||||
return d_lite_plus(self, other);
|
try_rational = 0;
|
||||||
#endif
|
goto again;
|
||||||
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case T_RATIONAL:
|
case T_RATIONAL:
|
||||||
{
|
{
|
||||||
VALUE nth, sf, t;
|
VALUE nth, sf, t;
|
||||||
int jd, df, s;
|
int jd, df, s;
|
||||||
|
|
||||||
if (wholenum_p(other))
|
if (wholenum_p(other)) {
|
||||||
return d_lite_plus(self, rb_rational_num(other));
|
other = rb_rational_num(other);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
if (f_positive_p(other))
|
if (f_positive_p(other))
|
||||||
s = +1;
|
s = +1;
|
||||||
|
@ -3,11 +3,18 @@ require 'test/unit'
|
|||||||
require 'date'
|
require 'date'
|
||||||
|
|
||||||
class TestDateArith < Test::Unit::TestCase
|
class TestDateArith < Test::Unit::TestCase
|
||||||
|
class Rat < Numeric
|
||||||
|
def to_r; self; end
|
||||||
|
end
|
||||||
|
|
||||||
def test_new_offset
|
def test_new_offset
|
||||||
d = DateTime.new(2002, 3, 14)
|
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(Rational(9, 24)).offset)
|
||||||
assert_equal(Rational(9, 24), d.new_offset('+0900').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
|
end
|
||||||
|
|
||||||
def test__plus
|
def test__plus
|
||||||
@ -37,6 +44,13 @@ class TestDateArith < Test::Unit::TestCase
|
|||||||
assert_raise(e) do
|
assert_raise(e) do
|
||||||
DateTime.new(2000,2,29) + Time.mktime(2000,2,29)
|
DateTime.new(2000,2,29) + Time.mktime(2000,2,29)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def test__minus
|
def test__minus
|
||||||
|
Loading…
x
Reference in New Issue
Block a user