diff --git a/src/common/function/test/FunctionManagerTest.cpp b/src/common/function/test/FunctionManagerTest.cpp index a1793aa1f54..20e460c4661 100644 --- a/src/common/function/test/FunctionManagerTest.cpp +++ b/src/common/function/test/FunctionManagerTest.cpp @@ -510,8 +510,9 @@ TEST_F(FunctionManagerTest, time) { { TEST_FUNCTION(date, {Map({{"year", 2021}, {"month", 4}, {"day", 31}})}, Value::kNullBadData); } // range [(−32,768, 1, 1), (32,767, 12, 31)] { - TEST_FUNCTION( - date, {Map({{"year", -32767}, {"month", 1}, {"day", 1}})}, Value(Date(-32767, 1, 1))); + TEST_FUNCTION(date, + {Map({{"year", std::numeric_limits::min()}, {"month", 1}, {"day", 1}})}, + Value(Date(std::numeric_limits::min(), 1, 1))); } { TEST_FUNCTION( @@ -686,13 +687,13 @@ TEST_F(FunctionManagerTest, time) { // range [(−32,768, 1, 1, 0, 0, 0, 0), (32,767, 12, 31, 23, 59, 59, 999999)] { TEST_FUNCTION(datetime, - {Map({{"year", -32767}, + {Map({{"year", -32768}, {"month", 1}, {"day", 1}, {"hour", 0}, {"minute", 0}, {"second", 0}})}, - Value(time::TimeUtils::dateTimeToUTC(DateTime(-32767, 1, 1, 0, 0, 0, 0)))); + Value(time::TimeUtils::dateTimeToUTC(DateTime(-32768, 1, 1, 0, 0, 0, 0)))); } { TEST_FUNCTION(datetime, diff --git a/src/common/time/TimeUtils.cpp b/src/common/time/TimeUtils.cpp index c6e9ee81771..0146bffd1d8 100644 --- a/src/common/time/TimeUtils.cpp +++ b/src/common/time/TimeUtils.cpp @@ -25,11 +25,11 @@ constexpr int64_t kMaxTimestamp = std::numeric_limits::max() / 10000000 return Status::Error("Invalid value type."); } if (kv.first == "year") { - // year should be in [-32767, 32767] and same as parser - if (kv.second.getInt() <= std::numeric_limits::min() || - kv.second.getInt() > std::numeric_limits::max()) { - return Status::Error("Out of range year `%ld'.", kv.second.getInt()); + auto result = validateYear(kv.second.getInt()); + if (!result.ok()) { + return result; } + dt.year = kv.second.getInt(); } else if (kv.first == "month") { if (kv.second.getInt() <= 0 || kv.second.getInt() > 12) { @@ -84,10 +84,9 @@ constexpr int64_t kMaxTimestamp = std::numeric_limits::max() / 10000000 return Status::Error("Invalid value type."); } if (kv.first == "year") { - // year should be in [-32767, 32767] and same as parser - if (kv.second.getInt() <= std::numeric_limits::min() || - kv.second.getInt() > std::numeric_limits::max()) { - return Status::Error("Out of range year `%ld'.", kv.second.getInt()); + auto result = validateYear(kv.second.getInt()); + if (!result.ok()) { + return result; } d.year = kv.second.getInt(); } else if (kv.first == "month") { diff --git a/src/common/time/TimeUtils.h b/src/common/time/TimeUtils.h index 1a3484f40ff..0fb2c27b615 100644 --- a/src/common/time/TimeUtils.h +++ b/src/common/time/TimeUtils.h @@ -52,6 +52,13 @@ class TimeUtils { return Status::OK(); } + static Status validateYear(int64_t year) { + if (year < std::numeric_limits::min() || year > std::numeric_limits::max()) { + return Status::Error("Out of range year `%ld'.", year); + } + return Status::OK(); + } + template < typename D, typename = std::enable_if_t::value || std::is_same::value>> diff --git a/src/common/time/parser/datetime_parser.yy b/src/common/time/parser/datetime_parser.yy index 34cfe92ed1e..e38d74f7f0d 100644 --- a/src/common/time/parser/datetime_parser.yy +++ b/src/common/time/parser/datetime_parser.yy @@ -114,48 +114,72 @@ date_time_delimiter date : INTEGER NEGATIVE INTEGER NEGATIVE INTEGER { + auto result = nebula::time::TimeUtils::validateYear($1); + if (!result.ok()) { + throw DatetimeParser::syntax_error(@1, result.toString()); + } $$ = new nebula::Date($1, $3, $5); - auto result = nebula::time::TimeUtils::validateDate(*$$); + result = nebula::time::TimeUtils::validateDate(*$$); if (!result.ok()) { delete $$; throw DatetimeParser::syntax_error(@1, result.toString()); } } | NEGATIVE INTEGER NEGATIVE INTEGER NEGATIVE INTEGER { + auto result = nebula::time::TimeUtils::validateYear(0-$2); + if (!result.ok()) { + throw DatetimeParser::syntax_error(@1, result.toString()); + } $$ = new nebula::Date(0-$2, $4, $6); - auto result = nebula::time::TimeUtils::validateDate(*$$); + result = nebula::time::TimeUtils::validateDate(*$$); if (!result.ok()) { delete $$; throw DatetimeParser::syntax_error(@1, result.toString()); } } | INTEGER NEGATIVE INTEGER { + auto result = nebula::time::TimeUtils::validateYear($1); + if (!result.ok()) { + throw DatetimeParser::syntax_error(@1, result.toString()); + } $$ = new nebula::Date($1, $3, 1); - auto result = nebula::time::TimeUtils::validateDate(*$$); + result = nebula::time::TimeUtils::validateDate(*$$); if (!result.ok()) { delete $$; throw DatetimeParser::syntax_error(@1, result.toString()); } } | NEGATIVE INTEGER NEGATIVE INTEGER { + auto result = nebula::time::TimeUtils::validateYear(0-$2); + if (!result.ok()) { + throw DatetimeParser::syntax_error(@1, result.toString()); + } $$ = new nebula::Date(0-$2, $4, 1); - auto result = nebula::time::TimeUtils::validateDate(*$$); + result = nebula::time::TimeUtils::validateDate(*$$); if (!result.ok()) { delete $$; throw DatetimeParser::syntax_error(@1, result.toString()); } } | INTEGER { + auto result = nebula::time::TimeUtils::validateYear($1); + if (!result.ok()) { + throw DatetimeParser::syntax_error(@1, result.toString()); + } $$ = new nebula::Date($1, 1, 1); - auto result = nebula::time::TimeUtils::validateDate(*$$); + result = nebula::time::TimeUtils::validateDate(*$$); if (!result.ok()) { delete $$; throw DatetimeParser::syntax_error(@1, result.toString()); } } | NEGATIVE INTEGER { + auto result = nebula::time::TimeUtils::validateYear(0-$2); + if (!result.ok()) { + throw DatetimeParser::syntax_error(@1, result.toString()); + } $$ = new nebula::Date(0-$2, 1, 1); - auto result = nebula::time::TimeUtils::validateDate(*$$); + result = nebula::time::TimeUtils::validateDate(*$$); if (!result.ok()) { delete $$; throw DatetimeParser::syntax_error(@1, result.toString()); diff --git a/src/common/time/parser/datetime_scanner.lex b/src/common/time/parser/datetime_scanner.lex index 98852c7c174..40cbb24f99a 100644 --- a/src/common/time/parser/datetime_scanner.lex +++ b/src/common/time/parser/datetime_scanner.lex @@ -39,7 +39,7 @@ R_BRACKET "]" {DEC}+ { try { folly::StringPiece text(yytext, yyleng); - int16_t val = folly::to(text); + int64_t val = folly::to(text); yylval->intVal = val; } catch (...) { throw DatetimeParser::syntax_error(*yylloc, "Invalid integer:");