diff --git a/mysql-test/suite/versioning/r/trx_id.result b/mysql-test/suite/versioning/r/trx_id.result index 9beec414fbba4..0b770d524876d 100644 --- a/mysql-test/suite/versioning/r/trx_id.result +++ b/mysql-test/suite/versioning/r/trx_id.result @@ -611,3 +611,21 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction disconnect con1; connection default; drop table t1; +# +# MDEV-40147 MSAN: use-of-uninitialized-value in my_time_compare +# +CREATE TABLE t ( +a INT, +row_start BIGINT UNSIGNED GENERATED ALWAYS AS ROW START, +row_end BIGINT UNSIGNED GENERATED ALWAYS AS ROW END, +PERIOD FOR SYSTEM_TIME (row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=InnoDB; +INSERT INTO t () VALUES (); +ANALYZE TABLE t PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze status OK +SELECT * FROM t WHERE row_end > CURRENT_TIME(); +ERROR HY000: TRX_ID ... not found in `mysql.transaction_registry` +DROP TABLE t; +# End of 10.11 tests diff --git a/mysql-test/suite/versioning/t/trx_id.test b/mysql-test/suite/versioning/t/trx_id.test index 8f96500f34005..90a773227512d 100644 --- a/mysql-test/suite/versioning/t/trx_id.test +++ b/mysql-test/suite/versioning/t/trx_id.test @@ -643,3 +643,26 @@ alter table xx; --disconnect con1 --connection default drop table t1; + +--echo # +--echo # MDEV-40147 MSAN: use-of-uninitialized-value in my_time_compare +--echo # + +CREATE TABLE t ( + a INT, + row_start BIGINT UNSIGNED GENERATED ALWAYS AS ROW START, + row_end BIGINT UNSIGNED GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (row_start, row_end) +) WITH SYSTEM VERSIONING ENGINE=InnoDB; + +INSERT INTO t () VALUES (); + +ANALYZE TABLE t PERSISTENT FOR ALL; + +--replace_regex /TRX_ID \d+/TRX_ID .../ +--error ER_VERS_NO_TRX_ID +SELECT * FROM t WHERE row_end > CURRENT_TIME(); + +DROP TABLE t; + +--echo # End of 10.11 tests diff --git a/sql/sql_time.h b/sql/sql_time.h index c918eb6d807ba..134f201959a04 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -121,7 +121,8 @@ int append_interval(String *str, interval_type int_type, */ bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, int lsign, MYSQL_TIME *l_time3, date_mode_t fuzzydate); -int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b); +int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b) + __attribute__((nonnull)); void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); void calc_time_from_sec(MYSQL_TIME *to, ulong seconds, ulong microseconds); @@ -183,8 +184,10 @@ check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, bool adjust_time_range_with_warn(THD *thd, MYSQL_TIME *ltime, uint dec); -longlong pack_time(const MYSQL_TIME *my_time); +longlong pack_time(const MYSQL_TIME *my_time) + __attribute__((nonnull)); void unpack_time(longlong packed, MYSQL_TIME *my_time, - enum_mysql_timestamp_type ts_type); + enum_mysql_timestamp_type ts_type) + __attribute__((nonnull)); #endif /* SQL_TIME_INCLUDED */ diff --git a/sql/sql_type.cc b/sql/sql_type.cc index c14a3ed564f52..0ea09e31a46ee 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -8951,7 +8951,7 @@ Type_handler_temporal_result::Item_const_eq(const Item_const *a, { const MYSQL_TIME *ta= a->const_ptr_mysql_time(); const MYSQL_TIME *tb= b->const_ptr_mysql_time(); - return !my_time_compare(ta, tb) && + return ta && tb && !my_time_compare(ta, tb) && (!binary_cmp || a->get_type_all_attributes_from_const()->decimals == b->get_type_all_attributes_from_const()->decimals); @@ -9107,10 +9107,10 @@ int Type_handler_temporal_with_date::stored_field_cmp_to_item(THD *thd, Item *item) const { MYSQL_TIME field_time, item_time, item_time2, *item_time_cmp= &item_time; - field->get_date(&field_time, Datetime::Options(TIME_INVALID_DATES, thd)); - item->get_date(thd, &item_time, Datetime::Options(TIME_INVALID_DATES, thd)); - if (item_time.time_type == MYSQL_TIMESTAMP_TIME && - time_to_datetime(thd, &item_time, item_time_cmp= &item_time2)) + if (field->get_date(&field_time, Datetime::Options(TIME_INVALID_DATES, thd)) + || item->get_date(thd, &item_time, Datetime::Options(TIME_INVALID_DATES, thd)) + || (item_time.time_type == MYSQL_TIMESTAMP_TIME && + time_to_datetime(thd, &item_time, item_time_cmp= &item_time2))) return 1; return my_time_compare(&field_time, item_time_cmp); } @@ -9121,8 +9121,10 @@ int Type_handler_time_common::stored_field_cmp_to_item(THD *thd, Item *item) const { MYSQL_TIME field_time, item_time; - field->get_date(&field_time, Time::Options(thd)); - item->get_date(thd, &item_time, Time::Options(thd)); + if (field->get_date(&field_time, Time::Options(thd))) + return -1; /* !=0 is important, and avoid my_time_compare */ + if (item->get_date(thd, &item_time, Time::Options(thd))) + return 1; /* !=0 is important, and avoid my_time_compare */ return my_time_compare(&field_time, &item_time); }