From 8b753ed2ab7bcf9b24dab4c0e7df750709efc548 Mon Sep 17 00:00:00 2001 From: "menglingda.mld" Date: Thu, 28 May 2026 17:24:34 +0800 Subject: [PATCH] fix: date validation reject invalid dates instead of silent normalization --- src/paimon/common/utils/string_utils.cpp | 8 ++++++-- src/paimon/common/utils/string_utils_test.cpp | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/paimon/common/utils/string_utils.cpp b/src/paimon/common/utils/string_utils.cpp index 3b92209a0..eb327a94e 100644 --- a/src/paimon/common/utils/string_utils.cpp +++ b/src/paimon/common/utils/string_utils.cpp @@ -140,8 +140,10 @@ Result StringUtils::StringToDate(const std::string& str) { if (ss.fail()) { return Status::Invalid(fmt::format("failed to convert string '{}' to date", str)); } + int32_t orig_mon = timeinfo.tm_mon; + int32_t orig_mday = timeinfo.tm_mday; std::time_t time = timegm(&timeinfo); - if (time == -1) { + if (time == -1 || timeinfo.tm_mon != orig_mon || timeinfo.tm_mday != orig_mday) { return Status::Invalid(fmt::format("failed to convert string '{}' to date", str)); } static const int64_t SECONDS_PER_DAY = 86400l; // = 24 * 60 * 60 @@ -207,8 +209,10 @@ Result StringUtils::StringToTimestampMillis(const std::string& str) { str)); } + int32_t orig_mon = timeinfo.tm_mon; + int32_t orig_mday = timeinfo.tm_mday; std::time_t time = mktime(&timeinfo); - if (time == -1) { + if (time == -1 || timeinfo.tm_mon != orig_mon || timeinfo.tm_mday != orig_mday) { return Status::Invalid(fmt::format("failed to convert string '{}' to timestamp", str)); } return static_cast(time) * 1000 + millis_part; diff --git a/src/paimon/common/utils/string_utils_test.cpp b/src/paimon/common/utils/string_utils_test.cpp index b4190d309..ec5811151 100644 --- a/src/paimon/common/utils/string_utils_test.cpp +++ b/src/paimon/common/utils/string_utils_test.cpp @@ -406,6 +406,8 @@ TEST_F(StringUtilsTest, TestStringToDate) { ASSERT_NOK(StringUtils::StringToDate("-1970-01-02")); ASSERT_NOK(StringUtils::StringToDate("")); ASSERT_NOK(StringUtils::StringToDate("1970-XX-02")); + ASSERT_NOK(StringUtils::StringToDate("2023-02-29")); + ASSERT_NOK(StringUtils::StringToDate("2024-00-01")); } TEST_F(StringUtilsTest, TestStringToTimestampMillis) { @@ -453,6 +455,8 @@ TEST_F(StringUtilsTest, TestStringToTimestampMillis) { ASSERT_NOK(StringUtils::StringToTimestampMillis("2023-06-01 00:00:00.12 ")); // Trailing dot with no digits ASSERT_NOK(StringUtils::StringToTimestampMillis("2023-06-01 00:00:00.")); + ASSERT_NOK(StringUtils::StringToTimestampMillis("2023-02-29 12:00:00")); + ASSERT_NOK(StringUtils::StringToTimestampMillis("2024-00-15 00:00:00")); } TEST_F(StringUtilsTest, TestVectorToString) {