Bug #116227 Some incorrect time should be detected
Submitted: 25 Sep 13:03 Modified: 26 Sep 8:19
Reporter: ximin liang (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: DML Severity:S3 (Non-critical)
Version: 9.0.1 OS:Any
Assigned to: CPU Architecture:Any

[25 Sep 13:03] ximin liang
Description:
Hello MySQL team:
  I found a case that MySQL servers does not detect some incorrect time.

How to repeat:
Can be repeated in MySQL 9.0.1

create table t1(c1 datetime);
explain select * from c1 where c1 = 271;
mysql> show warnings;
+---------+------+---------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                       |
+---------+------+---------------------------------------------------------------------------------------------------------------+
| Warning | 1292 | Incorrect datetime value: '271' for column 'c1' at row 1                                                      |
| Note    | 1003 | /* select#1 */ select `sqlengine`.`t1`.`c1` AS `c1` from `sqlengine`.`t1` where (`sqlengine`.`t1`.`c1` = 271) |
+---------+------+---------------------------------------------------------------------------------------------------------------+
from warnings, we can see that server detected that 271 is incorrect.

but if execute:
explain select * from t1 where c1 = 231;
mysql> show warnings;
+-------+------+------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                  |
+-------+------+------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `sqlengine`.`t1`.`c1` AS `c1` from `sqlengine`.`t1` where (`sqlengine`.`t1`.`c1` = TIMESTAMP'2000-02-31 00:00:00') |
+-------+------+------------------------------------------------------------------------------------------------------------------------------------------+

there is no warning.
Actually, 231 was treated as TIMESTAMP'2000-02-31 00:00:00' internally.

Suggested fix:
It is about func `check_datetime_range`, it does not conside leap year and corresponding max day for every month.

Here is my fix(based on 9.0.1):
diff --git a/mysys/my_time.cc b/mysys/my_time.cc
index ca8fdd30a63..0c377d4abc8 100644
--- a/mysys/my_time.cc
+++ b/mysys/my_time.cc
@@ -244,6 +244,23 @@ bool check_time_range_quick(const MYSQL_TIME &my_time) {
   return true;
 }
 
+/**
+  Check Date range according year, month, day value.
+  @param year  year value.
+  @param month  month value.
+  @param day  day value.
+  @retval false on success
+  @retval true  on error
+*/
+static bool check_date_range(uint year, uint month, uint day) {
+  if (year > 9999U || month > 12U || month == 0) return true;
+
+  bool is_leap_year = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
+  uint days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+  if (is_leap_year) days_in_month[1] = 29;
+  return day > days_in_month[month - 1];
+}
+
 /**
   Check datetime, date, or normalized time (i.e. time without days) range.
   @param my_time  Datetime value.
@@ -255,7 +272,7 @@ bool check_datetime_range(const MYSQL_TIME &my_time) {
     In case of MYSQL_TIMESTAMP_TIME hour value can be up to TIME_MAX_HOUR.
     In case of MYSQL_TIMESTAMP_DATETIME it cannot be bigger than 23.
   */
-  return my_time.year > 9999U || my_time.month > 12U || my_time.day > 31U ||
+  return check_date_range(my_time.year, my_time.month, my_time.day) ||
          my_time.minute > 59U || my_time.second > 59U ||
          my_time.second_part > 999999U ||
          (my_time.hour >
[26 Sep 8:19] MySQL Verification Team
Hello ximin liang,

Thank you for the report and test case.

regards,
Umesh
[26 Sep 8:20] MySQL Verification Team
Also, I see you have provided a patch with the bug report.

In order for us to continue the process of reviewing your contribution to MySQL, please send us a signed copy of the Oracle Contributor Agreement (OCA) as outlined in https://oca.opensource.oracle.com

Signing an OCA needs to be done only once and it's valid for all other Oracle governed Open Source projects as well.

Getting a signed/approved OCA on file will help us facilitate your contribution - this one, and others in the future.  

Please let me know, if you have any questions.

Thank you for your interest in MySQL.
[30 Sep 16:36] OCA Admin
Contribution submitted via Github - Bug #116227 Some incorrect time should be detected 
(*) Contribution by ximin liang (Github liangximin2046, mysql-server/pull/564#issuecomment-2380375050): I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

Contribution: git_patch_2093288477.txt (text/plain), 1.85 KiB.