← Back to team overview

maria-developers team mailing list archive

Please review MDEV-9604 crash in Item::save_in_field with empty enum value

 

Hi Sergei,

It fixes the reported crash, and additionally
inconsistencies when comparing temporal columns to empty strings:

In some cases it returned rows, in other cases it returned no rows,
depending on:
- the engine
- the type of comparison arguments (columns vs literals).
- presence of an index

Now everything works in the same way.


Note, this additional problem is not 10.1 specific, it existed in 10.0.
But 10.0 and 10.1 worked differently in certain cases.

Thanks!
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 155e953..16990c2 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -747,7 +747,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 FORCE INDEX(attime) WHERE AtTime = '2010-02-22
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ref	AtTime	AtTime	6	const	1	100.00	
 Warnings:
-Note	1003	select `test`.`t1`.`Id` AS `Id`,`test`.`t1`.`AtTime` AS `AtTime` from `test`.`t1` FORCE INDEX (`attime`) where (`test`.`t1`.`AtTime` = '2010-02-22 18:40:07')
+Note	1003	select `test`.`t1`.`Id` AS `Id`,`test`.`t1`.`AtTime` AS `AtTime` from `test`.`t1` FORCE INDEX (`attime`) where (`test`.`t1`.`AtTime` = TIMESTAMP'2010-02-22 18:40:07')
 DROP TABLE t1;
 SET NAMES latin1;
 #
@@ -963,21 +963,20 @@ a
 2001-01-01 00:00:00
 Warnings:
 Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
 Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = '2001-01-01 00:00:00x')
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00')
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)!=30+RAND() AND a='2001-01-01 00:00:00x';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
 Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '2001-01-01 00:00:00x') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand())))
 DROP TABLE t1;
 CREATE TABLE t1 (a DATETIME);;
 INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -993,20 +992,20 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = ' 2001-01-01 00:00:00')
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00')
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand())))
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
 Warning	1292	Incorrect datetime value: ' garbage '
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' garbage ') and (length(`test`.`t1`.`a`) = (30 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00') and (<cache>(length(TIMESTAMP'0000-00-00 00:00:00')) = (30 + rand())))
 DROP TABLE t1;
 CREATE TABLE t1 (a DATETIME);;
 INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -1076,13 +1075,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIME'00:00:00')
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00')
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIME'00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand())))
 DROP TABLE t1;
 #
 # MDEV-8795 Equal expression propagation does not work for temporal literals
diff --git a/mysql-test/r/type_temporal_innodb.result b/mysql-test/r/type_temporal_innodb.result
new file mode 100644
index 0000000..425e499a
--- /dev/null
+++ b/mysql-test/r/type_temporal_innodb.result
@@ -0,0 +1,156 @@
+#
+# MDEV-9604 crash in Item::save_in_field with empty enum value
+#
+SELECT TIME'00:00:00'='';
+TIME'00:00:00'=''
+1
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+CREATE TABLE t1 (a ENUM('a'), b TIME, c INT, KEY(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('','00:00:00',0);
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+SELECT * FROM t1 WHERE b='';
+a	b	c
+	00:00:00	0
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+a	b	c
+	00:00:00	0
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+SELECT * FROM t1 WHERE a=b;
+a	b	c
+	00:00:00	0
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+1
+1
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT * FROM t1 WHERE b='';
+a	b	c
+	00:00:00	0
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+a	b	c
+	00:00:00	0
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+SELECT * FROM t1 WHERE a=b;
+a	b	c
+	00:00:00	0
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+1
+1
+Warnings:
+Warning	1292	Truncated incorrect time value: ''
+DROP TABLE t1;
+SELECT DATE'0000-00-00'='';
+DATE'0000-00-00'=''
+1
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+CREATE TABLE t1 (a ENUM('a'), b DATE, c INT, KEY(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('','0000-00-00',0);
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+SELECT * FROM t1 WHERE b='';
+a	b	c
+	0000-00-00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+a	b	c
+	0000-00-00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 WHERE a=b;
+a	b	c
+	0000-00-00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+1
+1
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT * FROM t1 WHERE b='';
+a	b	c
+	0000-00-00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+a	b	c
+	0000-00-00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 WHERE a=b;
+a	b	c
+	0000-00-00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+1
+1
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+DROP TABLE t1;
+SELECT TIMESTAMP'0000-00-00 00:00:00'='';
+TIMESTAMP'0000-00-00 00:00:00'=''
+1
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+CREATE TABLE t1 (a ENUM('a'), b DATETIME, c INT, KEY(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('','0000-00-00 00:00:00',0);
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+SELECT * FROM t1 WHERE b='';
+a	b	c
+	0000-00-00 00:00:00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+a	b	c
+	0000-00-00 00:00:00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 WHERE a=b;
+a	b	c
+	0000-00-00 00:00:00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+1
+1
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT * FROM t1 WHERE b='';
+a	b	c
+	0000-00-00 00:00:00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+a	b	c
+	0000-00-00 00:00:00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT * FROM t1 WHERE a=b;
+a	b	c
+	0000-00-00 00:00:00	0
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+1
+1
+Warnings:
+Warning	1292	Incorrect datetime value: ''
+DROP TABLE t1;
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index fcdef62..a579f69 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -818,21 +818,20 @@ a
 2001-01-01 00:00:00
 Warnings:
 Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
 Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = '2001-01-01 00:00:00x')
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00')
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)!=30+RAND() AND a='2001-01-01 00:00:00x';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
 Warning	1292	Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '2001-01-01 00:00:00x') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand())))
 DROP TABLE t1;
 CREATE TABLE t1 (a TIMESTAMP);;
 INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -848,20 +847,20 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = ' 2001-01-01 00:00:00')
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00')
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand())))
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
 Warning	1292	Incorrect datetime value: ' garbage '
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' garbage ') and (length(`test`.`t1`.`a`) = (30 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00') and (<cache>(length(TIMESTAMP'0000-00-00 00:00:00')) = (30 + rand())))
 DROP TABLE t1;
 CREATE TABLE t1 (a TIMESTAMP);;
 INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -931,13 +930,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIME'00:00:00')
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00')
 EXPLAIN EXTENDED
 SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIME'00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand())))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand())))
 DROP TABLE t1;
 #
 # End of 10.1 tests
diff --git a/mysql-test/t/type_temporal_innodb.test b/mysql-test/t/type_temporal_innodb.test
new file mode 100644
index 0000000..ac5daca
--- /dev/null
+++ b/mysql-test/t/type_temporal_innodb.test
@@ -0,0 +1,60 @@
+--source include/have_innodb.inc
+
+#
+# testing of temporal data types with InnoDB
+#
+
+
+--echo #
+--echo # MDEV-9604 crash in Item::save_in_field with empty enum value
+--echo #
+
+SELECT TIME'00:00:00'='';
+
+CREATE TABLE t1 (a ENUM('a'), b TIME, c INT, KEY(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('','00:00:00',0);
+SELECT * FROM t1 WHERE b='';
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+SELECT * FROM t1 WHERE a=b;
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT * FROM t1 WHERE b='';
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+SELECT * FROM t1 WHERE a=b;
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+DROP TABLE t1;
+
+
+SELECT DATE'0000-00-00'='';
+
+CREATE TABLE t1 (a ENUM('a'), b DATE, c INT, KEY(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('','0000-00-00',0);
+SELECT * FROM t1 WHERE b='';
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+SELECT * FROM t1 WHERE a=b;
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT * FROM t1 WHERE b='';
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+SELECT * FROM t1 WHERE a=b;
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+DROP TABLE t1;
+
+
+SELECT TIMESTAMP'0000-00-00 00:00:00'='';
+
+CREATE TABLE t1 (a ENUM('a'), b DATETIME, c INT, KEY(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES ('','0000-00-00 00:00:00',0);
+SELECT * FROM t1 WHERE b='';
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+SELECT * FROM t1 WHERE a=b;
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+
+ALTER TABLE t1 ENGINE=MyISAM;
+SELECT * FROM t1 WHERE b='';
+SELECT * FROM t1 IGNORE KEY (b) WHERE b='';
+SELECT * FROM t1 WHERE a=b;
+SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b;
+DROP TABLE t1;
diff --git a/sql/field.cc b/sql/field.cc
index 895f8a0..ffa7beb 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5624,6 +5624,18 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd,
     }
     break;
   case ANY_SUBST:
+    if (!is_temporal_type_with_date(const_item->field_type()))
+    {
+      MYSQL_TIME ltime;
+      if (const_item->get_date_with_conversion(&ltime,
+                                               TIME_FUZZY_DATES |
+                                               TIME_INVALID_DATES))
+        return NULL;
+      return new (thd->mem_root)
+        Item_datetime_literal_for_invalid_dates(thd, &ltime,
+                                                ltime.second_part ?
+                                                TIME_SECOND_PART_DIGITS : 0);
+    }
     break;
   }
   return const_item;
@@ -5932,7 +5944,10 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
     {
       MYSQL_TIME ltime;
       // Get the value of const_item with conversion from DATETIME to TIME
-      if (const_item->get_time_with_conversion(thd, &ltime, TIME_TIME_ONLY))
+      if (const_item->get_time_with_conversion(thd, &ltime,
+                                               TIME_TIME_ONLY |
+                                               TIME_FUZZY_DATES |
+                                               TIME_INVALID_DATES))
         return NULL;
       /*
         Replace a DATE/DATETIME constant to a TIME constant:
diff --git a/sql/item.cc b/sql/item.cc
index a330cee..fe49ce4 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1301,6 +1301,22 @@ bool Item::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
     if allowed, otherwise - null.
   */
   bzero((char*) ltime,sizeof(*ltime));
+  if (fuzzydate & TIME_TIME_ONLY)
+  {
+    /*
+      In the following scenario:
+      - The caller expected to get a TIME value
+      - Item returned a not NULL string or numeric value
+      - But then conversion from string or number to TIME failed
+      we need to change the default time_type from MYSQL_TIMESTAMP_DATE
+      (which was set in bzero) to MYSQL_TIMESTAMP_TIME and therefore
+      return TIME'00:00:00' rather than DATE'0000-00-00'.
+      If we don't do this, methods like Item::get_time_with_conversion()
+      will erroneously subtract CURRENT_DATE from '0000-00-00 00:00:00'
+      and return TIME'-838:59:59' instead of TIME'00:00:00' as a result.
+    */
+    ltime->time_type= MYSQL_TIMESTAMP_TIME;
+  }
   return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
 }
 

Follow ups