diff --git a/be/src/runtime/datetime_value.cpp b/be/src/runtime/datetime_value.cpp index 67be08190fb724..29e4761e00da1b 100644 --- a/be/src/runtime/datetime_value.cpp +++ b/be/src/runtime/datetime_value.cpp @@ -74,10 +74,7 @@ bool DateTimeValue::check_range() const { } bool DateTimeValue::check_date() const { - if (_month == 0 || _day == 0) { - return true; - } - if (_day > s_days_in_month[_month]) { + if (_month != 0 && _day > s_days_in_month[_month]) { // Feb 29 in leap year is valid. if (_month == 2 && _day == 29 && is_leap(_year)) { return false; diff --git a/be/test/runtime/datetime_value_test.cpp b/be/test/runtime/datetime_value_test.cpp index 4d49cc90bd7124..e69535eb357fbe 100644 --- a/be/test/runtime/datetime_value_test.cpp +++ b/be/test/runtime/datetime_value_test.cpp @@ -236,11 +236,11 @@ TEST_F(DateTimeValueTest, check_date) { ASSERT_TRUE(value.from_date_int64(19880201)); value._month = 0; - ASSERT_TRUE(value.check_date()); + ASSERT_FALSE(value.check_date()); value._month = 2; value._day = 0; - ASSERT_TRUE(value.check_date()); + ASSERT_FALSE(value.check_date()); value._year = 1987; value._day = 29; ASSERT_TRUE(value.check_date()); @@ -1185,6 +1185,7 @@ TEST_F(DateTimeValueTest, from_int_value) { // Construct from int value invalid TEST_F(DateTimeValueTest, from_int_value_invalid) { DateTimeValue value; + char str[MAX_DTVALUE_STR_LEN]; // minus value ASSERT_FALSE(value.from_date_int64(-1231)); // [0, 101) @@ -1198,7 +1199,10 @@ TEST_F(DateTimeValueTest, from_int_value_invalid) { // 100-12-31 ASSERT_FALSE(value.from_date_int64(1232)); // 99 00:00:00 - ASSERT_FALSE(value.from_date_int64(99000000)); + ASSERT_TRUE(value.from_date_int64(99000000)); + value.to_string(str); + ASSERT_STREQ("9900-00-00", str); + // 9999-99-99 99:99:99 + 1 ASSERT_FALSE(value.from_date_int64(99999999999999L + 1)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java index 257e6fd1b083c6..a9cc822c23e5df 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java @@ -62,6 +62,7 @@ public class DateLiteral extends LiteralExpr { public static final DateLiteral UNIX_EPOCH_TIME = new DateLiteral(1970, 01, 01, 00, 00, 00); private static final int DATEKEY_LENGTH = 8; + private static final int MAX_MICROSECOND = 999999; private static DateTimeFormatter DATE_TIME_FORMATTER = null; private static DateTimeFormatter DATE_FORMATTER = null; @@ -1035,12 +1036,35 @@ public int fromDateFormatStr(String format, String value, boolean hasSubVal) thr this.type = Type.DATE; } } + + if (checkRange() || checkDate()) { + throw new InvalidFormatException("Invalid format"); + } return 0; } + private boolean checkRange() { + return year > MAX_DATETIME.year || month > MAX_DATETIME.month || day > MAX_DATETIME.day + || hour > MAX_DATETIME.hour || minute > MAX_DATETIME.minute || second > MAX_DATETIME.second + || microsecond > MAX_MICROSECOND; + } + private boolean checkDate() { + if (month != 0 && day > DAYS_IN_MONTH.get((int)month)){ + if (month == 2 && day == 29 && Year.isLeap(year)) { + return false; + } + return true; + } + return false; + } + private long strToLong(String l) throws InvalidFormatException { try { - return Long.valueOf(l); + long y = Long.valueOf(l); + if (y < 0) { + throw new InvalidFormatException("Invalid format: negative number."); + } + return y; } catch (NumberFormatException e) { throw new InvalidFormatException(e.getMessage()); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java index 02b165b5d30947..9b94f9d912e1cb 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java @@ -19,6 +19,8 @@ import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.InvalidFormatException; +import org.apache.doris.common.jmockit.Deencapsulation; import org.junit.Assert; import org.junit.Test; @@ -74,4 +76,43 @@ public void uncheckedCastTo() { } Assert.assertFalse(hasException); } + + @Test + public void testCheckDate() { + boolean hasException = false; + try { + DateLiteral dateLiteral = new DateLiteral(); + dateLiteral.fromDateFormatStr("%Y%m%d","19971007", false); + Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate")); + + dateLiteral.fromDateFormatStr("%Y%m%d","19970007", false); + Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate")); + + dateLiteral.fromDateFormatStr("%Y%m%d","19971000", false); + Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate")); + + dateLiteral.fromDateFormatStr("%Y%m%d","20000229", false); + Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkDate")); + + } catch (InvalidFormatException e) { + e.printStackTrace(); + hasException = true; + } + Assert.assertFalse(hasException); + } + + @Test + public void testCheckRange() { + boolean hasException = false; + try { + DateLiteral dateLiteral = new DateLiteral(); + dateLiteral.fromDateFormatStr("%Y%m%d%H%i%s%f","20201209123456123456", false); + Assert.assertFalse(Deencapsulation.invoke(dateLiteral, "checkRange")); + + } catch (InvalidFormatException e) { + e.printStackTrace(); + hasException = true; + } + Assert.assertFalse(hasException); + } }