ruby-changes:50450
From: nobu <ko1@a...>
Date: Sun, 25 Feb 2018 13:28:17 +0900 (JST)
Subject: [ruby-changes:50450] nobu:r62572 (trunk): date_core.c: defensive code
nobu 2018-02-25 13:28:11 +0900 (Sun, 25 Feb 2018) New Revision: 62572 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62572 Log: date_core.c: defensive code * ext/date/date_core.c (f_cmp): check comparison failure. * ext/date/date_core.c (d_lite_step): deal with the comparison result more defensively. [ruby-core:85796] [Bug #14549] Modified files: trunk/ext/date/date_core.c trunk/test/date/test_date_arith.rb Index: ext/date/date_core.c =================================================================== --- ext/date/date_core.c (revision 62571) +++ ext/date/date_core.c (revision 62572) @@ -51,18 +51,18 @@ static double positive_inf, negative_inf https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L51 #define f_add3(x,y,z) f_add(f_add(x, y), z) #define f_sub3(x,y,z) f_sub(f_sub(x, y), z) -inline static VALUE +inline static int f_cmp(VALUE x, VALUE y) { if (FIXNUM_P(x) && FIXNUM_P(y)) { long c = FIX2LONG(x) - FIX2LONG(y); if (c > 0) - c = 1; + return 1; else if (c < 0) - c = -1; - return INT2FIX(c); + return -1; + return 0; } - return rb_funcall(x, id_cmp, 1, y); + return rb_cmpint(rb_funcallv(x, id_cmp, 1, &y), x, y); } inline static VALUE @@ -6154,6 +6154,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L6154 d_lite_step(int argc, VALUE *argv, VALUE self) { VALUE limit, step, date; + int c; rb_scan_args(argc, argv, "11", &limit, &step); @@ -6168,25 +6169,22 @@ d_lite_step(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L6169 RETURN_ENUMERATOR(self, argc, argv); date = self; - switch (FIX2INT(f_cmp(step, INT2FIX(0)))) { - case -1: + c = f_cmp(step, INT2FIX(0)); + if (c < 0) { while (FIX2INT(d_lite_cmp(date, limit)) >= 0) { rb_yield(date); date = d_lite_plus(date, step); } - break; - case 0: + } + else if (c == 0) { while (1) rb_yield(date); - break; - case 1: + } + else /* if (c > 0) */ { while (FIX2INT(d_lite_cmp(date, limit)) <= 0) { rb_yield(date); date = d_lite_plus(date, step); } - break; - default: - abort(); } return self; } @@ -6241,9 +6239,9 @@ cmp_gen(VALUE self, VALUE other) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L6239 get_d1(self); if (k_numeric_p(other)) - return f_cmp(m_ajd(dat), other); + return INT2FIX(f_cmp(m_ajd(dat), other)); else if (k_date_p(other)) - return f_cmp(m_ajd(dat), f_ajd(other)); + return INT2FIX(f_cmp(m_ajd(dat), f_ajd(other))); return rb_num_coerce_cmp(self, other, rb_intern("<=>")); } Index: test/date/test_date_arith.rb =================================================================== --- test/date/test_date_arith.rb (revision 62571) +++ test/date/test_date_arith.rb (revision 62572) @@ -262,4 +262,17 @@ class TestDateArith < Test::Unit::TestCa https://github.com/ruby/ruby/blob/trunk/test/date/test_date_arith.rb#L262 assert_equal(8, e.to_a.size) end + def test_step__compare + o = Object.new + def o.<=>(*);end + assert_raise(ArgumentError) { + Date.new(2000, 1, 1).step(3, o).to_a + } + + o = Object.new + def o.<=>(*);2;end + a = [] + Date.new(2000, 1, 1).step(3, o) {|d| a << d} + assert_empty(a) + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/