From 5685abe6c3b028bb72647305987cdea694cd78e2 Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 17 Aug 2013 13:20:50 +0000 Subject: [PATCH] time.c: ignore invalid data * time.c (time_mload): ignore invalid offset and zone. [ruby-core:56648] [Bug #8795] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ test/ruby/test_time.rb | 37 +++++++++++++++++++++++++++++++++++++ time.c | 20 +++++++++++++++----- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index fcd40576d2..c772892a27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sat Aug 17 22:20:47 2013 Nobuyoshi Nakada + + * time.c (time_mload): ignore invalid offset and zone. + [ruby-core:56648] [Bug #8795] + Sat Aug 17 20:11:49 2013 Benoit Daloze * process.c: [DOC] MACH_ABSOLUTE_TIME_CLOCK_MONOTONIC is an diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb index 2a56836cce..e57601917d 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -312,6 +312,43 @@ class TestTime < Test::Unit::TestCase "[ruby-dev:44827] [Bug #5586]") end + def in_timezone(zone) + orig_zone = ENV['TZ'] + + ENV['TZ'] = 'UTC' + yield + ensure + ENV['TZ'] = orig_zone + end + + Bug8795 = '[ruby-core:56648] [Bug #8795]' + + def test_marshal_broken_offset + data = "\x04\bIu:\tTime\r\xEFF\x1C\x80\x00\x00\x00\x00\x06:\voffset" + t1 = t2 = nil + in_timezone('UTC') do + assert_nothing_raised(TypeError, ArgumentError, Bug8795) do + t1 = Marshal.load(data + "T") + t2 = Marshal.load(data + "\"\x0ebadoffset") + end + assert_equal(0, t1.utc_offset) + assert_equal(0, t2.utc_offset) + end + end + + def test_marshal_broken_zone + data = "\x04\bIu:\tTime\r\xEFF\x1C\x80\x00\x00\x00\x00\x06:\tzone" + t1 = t2 = nil + in_timezone('UTC') do + assert_nothing_raised(TypeError, ArgumentError, Bug8795) do + t1 = Marshal.load(data + "T") + t2 = Marshal.load(data + "\"\b\0\0\0") + end + assert_equal('UTC', t1.zone) + assert_equal('UTC', t2.zone) + end + end + def test_at3 t2000 = get_t2000 assert_equal(t2000, Time.at(t2000)) diff --git a/time.c b/time.c index 68a6b7e95e..8c04956666 100644 --- a/time.c +++ b/time.c @@ -754,7 +754,8 @@ static VALUE time_utc_offset _((VALUE)); static int obj2int(VALUE obj); static VALUE obj2vint(VALUE obj); static int month_arg(VALUE arg); -static void validate_utc_offset(VALUE utc_offset); +static VALUE validate_utc_offset(VALUE utc_offset); +static VALUE validate_zone_name(VALUE zone_name); static void validate_vtm(struct vtm *vtm); static int obj2subsecx(VALUE obj, VALUE *subsecx); @@ -2581,11 +2582,19 @@ month_arg(VALUE arg) return mon; } -static void +static VALUE validate_utc_offset(VALUE utc_offset) { if (le(utc_offset, INT2FIX(-86400)) || ge(utc_offset, INT2FIX(86400))) rb_raise(rb_eArgError, "utc_offset out of range"); + return utc_offset; +} + +static VALUE +validate_zone_name(VALUE zone_name) +{ + StringValueCStr(zone_name); + return zone_name; } static void @@ -4702,8 +4711,9 @@ time_mload(VALUE time, VALUE str) get_attr(nano_num, {}); get_attr(nano_den, {}); get_attr(submicro, {}); - get_attr(offset, validate_utc_offset(offset)); - get_attr(zone, {}); + get_attr(offset, (offset = rb_rescue(validate_utc_offset, offset, NULL, Qnil))); + get_attr(zone, (zone = rb_rescue(validate_zone_name, zone, NULL, Qnil))); + #undef get_attr rb_copy_generic_ivar(time, str); @@ -4789,7 +4799,7 @@ end_submicro: ; time_fixoff(time); } if (!NIL_P(zone)) { - tobj->vtm.zone = StringValueCStr(zone); + tobj->vtm.zone = RSTRING_PTR(zone); } return time;