Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 36 additions & 23 deletions ext/date/date_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ s3e(VALUE hash, VALUE y, VALUE m, VALUE d, int bc)
#define ABBR_DAYS "sun|mon|tue|wed|thu|fri|sat"
#define ABBR_MONTHS "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec"

#define NUMBER "(?<!\\d)\\d"

#ifdef TIGHT_PARSER
#define VALID_DAYS "(?:" DAYS ")" "|(?:tues|wednes|thurs|thur|" ABBR_DAYS ")\\.?"
#define VALID_MONTHS "(?:" MONTHS ")" "|(?:sept|" ABBR_MONTHS ")\\.?"
Expand Down Expand Up @@ -652,24 +654,27 @@ parse_time(VALUE str, VALUE hash)
{
static const char pat_source[] =
"("
"" NUMBER "+\\s*"
"(?:"
"\\d+\\s*:\\s*\\d+"
"(?:"
":\\s*\\d+"
"(?:"
#ifndef TIGHT_PARSER
"\\s*:\\s*\\d+(?:[,.]\\d*)?"
"\\s*:\\s*\\d+(?:[,.]\\d*)?"
#else
"\\s*:\\s*\\d+(?:[,.]\\d+)?"
"\\s*:\\s*\\d+(?:[,.]\\d+)?"
#endif
")?"
"|"
"h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
")"
"(?:"
"\\s*"
"[ap](?:m\\b|\\.m\\.)"
")?"
"|"
"\\d+\\s*h(?:\\s*\\d+m?(?:\\s*\\d+s?)?)?"
")"
"(?:"
"\\s*"
"[ap](?:m\\b|\\.m\\.)"
")?"
"|"
"\\d+\\s*[ap](?:m\\b|\\.m\\.)"
")"
")"
"(?:"
"\\s*"
Expand All @@ -691,6 +696,9 @@ parse_time(VALUE str, VALUE hash)
#endif
}

#define BEGIN_ERA "\\b"
#define END_ERA "(?!(?<!\\.)[a-z])"

#ifdef TIGHT_PARSER
static int
parse_era1_cb(VALUE m, VALUE hash)
Expand All @@ -702,7 +710,7 @@ static int
parse_era1(VALUE str, VALUE hash)
{
static const char pat_source[] =
"(a(?:d|\\.d\\.))";
BEGIN_ERA "(a(?:d\\b|\\.d\\.))" END_ERA;
static VALUE pat = Qnil;

REGCOMP_I(pat);
Expand All @@ -724,8 +732,9 @@ parse_era2_cb(VALUE m, VALUE hash)
static int
parse_era2(VALUE str, VALUE hash)
{
static const char pat_source[] =
"(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|b(?:c|\\.c\\.))";
static const char pat_source[] = BEGIN_ERA
"(c(?:e\\b|\\.e\\.)|b(?:ce\\b|\\.c\\.e\\.)|b(?:c\\b|\\.c\\.))"
END_ERA;
static VALUE pat = Qnil;

REGCOMP_I(pat);
Expand Down Expand Up @@ -829,7 +838,7 @@ parse_eu(VALUE str, VALUE hash)
FPW_COM FPT_COM
#endif
#ifndef TIGHT_PARSER
"('?\\d+)[^-\\d\\s]*"
"('?" NUMBER "+)[^-\\d\\s]*"
#else
"(\\d+)(?:(?:st|nd|rd|th)\\b)?"
#endif
Expand All @@ -842,7 +851,11 @@ parse_eu(VALUE str, VALUE hash)
"(?:"
"\\s*"
#ifndef TIGHT_PARSER
"(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
"(?:"
BEGIN_ERA
"(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))"
END_ERA
")?"
"\\s*"
"('?-?\\d+(?:(?:st|nd|rd|th)\\b)?)"
#else
Expand Down Expand Up @@ -919,8 +932,8 @@ parse_us(VALUE str, VALUE hash)
COM_FPT
#endif
"(?:"
"\\s*,?"
"\\s*"
"\\s*+,?"
"\\s*+"
#ifndef TIGHT_PARSER
"(c(?:e|\\.e\\.)|b(?:ce|\\.c\\.e\\.)|a(?:d|\\.d\\.)|b(?:c|\\.c\\.))?"
"\\s*"
Expand Down Expand Up @@ -967,7 +980,7 @@ parse_iso(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
"('?[-+]?\\d+)-(\\d+)-('?-?\\d+)"
"('?[-+]?" NUMBER "+)-(\\d+)-('?-?\\d+)"
#else
BOS
FPW_COM FPT_COM
Expand Down Expand Up @@ -1321,7 +1334,7 @@ parse_vms11(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
"('?-?\\d+)-(" ABBR_MONTHS ")[^-/.]*"
"('?-?" NUMBER "+)-(" ABBR_MONTHS ")[^-/.]*"
"-('?-?\\d+)"
#else
BOS
Expand Down Expand Up @@ -1416,7 +1429,7 @@ parse_sla(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
"('?-?\\d+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
"('?-?" NUMBER "+)/\\s*('?\\d+)(?:\\D\\s*('?-?\\d+))?"
#else
BOS
FPW_COM FPT_COM
Expand Down Expand Up @@ -1524,7 +1537,7 @@ parse_dot(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
"('?-?\\d+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
"('?-?" NUMBER "+)\\.\\s*('?\\d+)\\.\\s*('?-?\\d+)"
#else
BOS
FPW_COM FPT_COM
Expand Down Expand Up @@ -1684,7 +1697,7 @@ parse_mday(VALUE str, VALUE hash)
{
static const char pat_source[] =
#ifndef TIGHT_PARSER
"(\\d+)(st|nd|rd|th)\\b"
"(" NUMBER "+)(st|nd|rd|th)\\b"
#else
BOS
FPW_COM FPT_COM
Expand Down Expand Up @@ -1922,7 +1935,7 @@ parse_ddd(VALUE str, VALUE hash)
#ifdef TIGHT_PARSER
BOS
#endif
"([-+]?)(\\d{2,14})"
"([-+]?)(" NUMBER "{2,14})"
"(?:"
"\\s*"
"t?"
Expand Down
15 changes: 13 additions & 2 deletions test/date/test_date_parse.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'test/unit'
require 'date'
require 'timeout'
require 'envutil'

class TestDateParse < Test::Unit::TestCase

Expand Down Expand Up @@ -585,6 +585,18 @@ def test__parse_odd_offset
assert_equal(5025, h[:offset])
end

def test__parse_too_long_year
str = "Jan 1" + "0" * 100_000
h = EnvUtil.timeout(1) {Date._parse(str, limit: 100_010)}
assert_equal(100_000, Math.log10(h[:year]))
assert_equal(1, h[:mon])

str = "Jan - 1" + "0" * 100_000
h = EnvUtil.timeout(1) {Date._parse(str, limit: 100_010)}
assert_equal(1, h[:mon])
assert_not_include(h, :year)
end

require 'time'

def test_parse__time
Expand Down Expand Up @@ -1297,6 +1309,5 @@ def test_length_limit
assert_raise(ArgumentError) { DateTime.jisx0301("1" * 1000) }

assert_raise(ArgumentError) { Date._parse("Jan " + "9" * 1000000) }
assert_raise(Timeout::Error) { Timeout.timeout(1) { Date._parse("Jan " + "9" * 1000000, limit: nil) } }
end
end