[Bug #19296] Precheck bits of time components

This commit is contained in:
Nobuyoshi Nakada 2023-01-02 23:23:53 +09:00
Родитель 291a4098cf
Коммит 5be0d42d2c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 7CD2805BFA3770C6
2 изменённых файлов: 23 добавлений и 6 удалений

Просмотреть файл

@ -99,30 +99,45 @@ class TestTime < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /two digits sec.*:9\b/) {
Time.new("2020-12-25 00:56:9 +0900")
}
assert_raise_with_message(ArgumentError, /sec out of range/) {
Time.new("2020-12-25 00:56:64 +0900")
}
assert_raise_with_message(ArgumentError, /two digits min.*:056\b/) {
Time.new("2020-12-25 00:056:17 +0900")
}
assert_raise_with_message(ArgumentError, /two digits min.*:5\b/) {
Time.new("2020-12-25 00:5:17 +0900")
}
assert_raise_with_message(ArgumentError, /min out of range/) {
Time.new("2020-12-25 00:64:17 +0900")
}
assert_raise_with_message(ArgumentError, /two digits hour.*\b000\b/) {
Time.new("2020-12-25 000:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /two digits hour.*\b0\b/) {
Time.new("2020-12-25 0:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /hour out of range/) {
Time.new("2020-12-25 33:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /two digits mday.*\b025\b/) {
Time.new("2020-12-025 00:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /two digits mday.*\b5\b/) {
Time.new("2020-12-5 00:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /mday out of range/) {
Time.new("2020-12-33 00:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /two digits mon.*\b012\b/) {
Time.new("2020-012-25 00:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /two digits mon.*\b1\b/) {
Time.new("2020-1-25 00:56:17 +0900")
}
assert_raise_with_message(ArgumentError, /mon out of range/) {
Time.new("2020-17-25 00:56:17 +0900")
}
end
def test_time_add()

14
time.c
Просмотреть файл

@ -2541,11 +2541,13 @@ time_init_parse(rb_execution_context_t *ec, VALUE klass, VALUE str, VALUE zone,
#define peek(c) peek_n(c, 0)
#define peekc_n(n) (peekable_p(n) ? (int)(unsigned char)ptr[n] : -1)
#define peekc() peekc_n(0)
#define expect_two_digits(x) (x = two_digits(ptr + 1, end, &ptr, #x))
#define expect_two_digits(x, bits) \
(((unsigned int)(x = two_digits(ptr + 1, end, &ptr, #x)) > (1U << bits) - 1) ? \
rb_raise(rb_eArgError, #x" out of range") : (void)0)
if (!peek('-')) break;
expect_two_digits(mon);
expect_two_digits(mon, 4);
if (!peek('-')) break;
expect_two_digits(mday);
expect_two_digits(mday, 5);
if (!peek(' ') && !peek('T')) break;
const char *const time_part = ptr + 1;
if (!ISDIGIT(peekc_n(1))) break;
@ -2559,13 +2561,13 @@ time_init_parse(rb_execution_context_t *ec, VALUE klass, VALUE str, VALUE zone,
rb_raise(rb_eArgError, "missing " #x " part: %.*s", \
(int)(ptr + 1 - time_part), time_part); \
}
expect_two_digits(hour);
expect_two_digits(hour, 5);
nofraction(hour);
need_colon(min);
expect_two_digits(min);
expect_two_digits(min, 6);
nofraction(min);
need_colon(sec);
expect_two_digits(sec);
expect_two_digits(sec, 6);
if (peek('.')) {
ptr++;
for (ndigits = 0; ndigits < prec && ISDIGIT(peekc_n(ndigits)); ++ndigits);