diff options
| author | nagachika <nagachika@ruby-lang.org> | 2023-07-23 12:20:12 +0900 |
|---|---|---|
| committer | nagachika <nagachika@ruby-lang.org> | 2023-07-23 12:20:12 +0900 |
| commit | 0b3ed6043c9d091d499ca1caed604a983c7e285b (patch) | |
| tree | 7294b31aa3fcd86585c6302309f24df8e1a5a575 | |
| parent | 3354aacb73c65420a10cb41c0696e62dd1ba279b (diff) | |
merge revision(s) 5d4fff845602872eef072e7611558b5f8762efe0: [Backport #19293]
Tighten Time.new(string) parsing
Disallow:
* Only year-month
* Only year-month-day
* Preceding whitespace
* Trailing whitespace
Fixes [Bug #19293]
---
test/ruby/test_time.rb | 13 +++++++++++++
time.c | 13 ++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
| -rw-r--r-- | test/ruby/test_time.rb | 13 | ||||
| -rw-r--r-- | time.c | 13 | ||||
| -rw-r--r-- | version.h | 2 |
3 files changed, 26 insertions, 2 deletions
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb index f47a49d3e0..0faad878fc 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -75,6 +75,7 @@ class TestTime < Test::Unit::TestCase Time.new("2020-12-25 00 +09:00") } + assert_equal(Time.new(2021), Time.new("2021")) assert_equal(Time.new(2021, 12, 25, in: "+09:00"), Time.new("2021-12-25+09:00")) assert_equal(0.123456r, Time.new("2021-12-25 00:00:00.123456 +09:00").subsec) @@ -138,6 +139,18 @@ class TestTime < Test::Unit::TestCase assert_raise_with_message(ArgumentError, /mon out of range/) { Time.new("2020-17-25 00:56:17 +0900") } + assert_raise_with_message(ArgumentError, /no time information/) { + Time.new("2020-12") + } + assert_raise_with_message(ArgumentError, /no time information/) { + Time.new("2020-12-02") + } + assert_raise_with_message(ArgumentError, /can't parse/) { + Time.new(" 2020-12-02 00:00:00") + } + assert_raise_with_message(ArgumentError, /can't parse/) { + Time.new("2020-12-02 00:00:00 ") + } end def test_time_add() @@ -2525,7 +2525,9 @@ time_init_parse(rb_execution_context_t *ec, VALUE klass, VALUE str, VALUE zone, size_t ndigits; size_t prec = NIL_P(precision) ? SIZE_MAX : NUM2SIZET(precision); - while ((ptr < end) && ISSPACE(*ptr)) ptr++; + if ((ptr < end) && (ISSPACE(*ptr) || ISSPACE(*(end-1)))) { + rb_raise(rb_eArgError, "can't parse: %+"PRIsVALUE, str); + } year = parse_int(ptr, end, &ptr, &ndigits, true); if (NIL_P(year)) { rb_raise(rb_eArgError, "can't parse: %+"PRIsVALUE, str); @@ -2533,6 +2535,9 @@ time_init_parse(rb_execution_context_t *ec, VALUE klass, VALUE str, VALUE zone, else if (ndigits < 4) { rb_raise(rb_eArgError, "year must be 4 or more digits: %.*s", (int)ndigits, ptr - ndigits); } + else if (ptr == end) { + goto only_year; + } do { #define peekable_p(n) ((ptrdiff_t)(n) < (end - ptr)) #define peek_n(c, n) (peekable_p(n) && ((unsigned char)ptr[n] == (c))) @@ -2593,6 +2598,9 @@ time_init_parse(rb_execution_context_t *ec, VALUE klass, VALUE str, VALUE zone, if (zend > zstr) { zone = rb_str_subseq(str, zstr - begin, zend - zstr); } + else if (hour == -1) { + rb_raise(rb_eArgError, "no time information"); + } if (!NIL_P(subsec)) { /* subseconds is the last using ndigits */ static const size_t TIME_SCALE_NUMDIGITS = @@ -2609,6 +2617,9 @@ time_init_parse(rb_execution_context_t *ec, VALUE klass, VALUE str, VALUE zone, } } +only_year: + ; + struct vtm vtm = { .wday = VTM_WDAY_INITVAL, .yday = 0, @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 2 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 104 +#define RUBY_PATCHLEVEL 105 #include "ruby/version.h" #include "ruby/internal/abi.h" |
