summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-03-14 10:05:38 +0400
committerAlexander Barkov <bar@mariadb.com>2019-03-14 10:05:38 +0400
commitcb66cdc6f80a32b9ea363f8d59ccb665730a4464 (patch)
tree542bc5190793c27d3331fa918bf22507813e9f02
parentd7a38eaf1a3b3138a77156a64fba7f90a5dc6257 (diff)
downloadmariadb-git-cb66cdc6f80a32b9ea363f8d59ccb665730a4464.tar.gz
MDEV-14926 AddressSanitizer: heap-use-after-free in make_date_time on weird combination of functions
-rw-r--r--mysql-test/r/func_time.result16
-rw-r--r--mysql-test/t/func_time.test18
-rw-r--r--sql/item_timefunc.cc16
3 files changed, 40 insertions, 10 deletions
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index f0652236a38..1c3d69c6a6b 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -3420,5 +3420,21 @@ t2 CREATE TABLE `t2` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1,t2;
#
+# MDEV-14926 AddressSanitizer: heap-use-after-free in make_date_time on weird combination of functions
+#
+DO INET_ATON( FROM_UNIXTIME( @@timestamp, ( TRIM( UNHEX(HEX('%m.%d.%Y') ) ) ) ) );
+CREATE TABLE t1 (d DATE);
+INSERT INTO t1 VALUES ('1989-03-10');
+SELECT TIME_FORMAT('23:59:43', BINARY d) AS f FROM t1 GROUP BY 'foo';
+f
+1989-03-10
+DROP TABLE t1;
+CREATE TABLE t1 (d DATE) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('1900-01-01');
+SELECT LENGTH( DATE_FORMAT( d, BINARY DATABASE() ) ) AS f FROM t1 GROUP BY d;
+f
+4
+DROP TABLE t1;
+#
# End of 10.1 tests
#
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 0a4b85c2a81..12356ff3646 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -1906,6 +1906,24 @@ SELECT * FROM t2;
SHOW CREATE TABLE t2;
DROP TABLE t1,t2;
+
+--echo #
+--echo # MDEV-14926 AddressSanitizer: heap-use-after-free in make_date_time on weird combination of functions
+--echo #
+
+DO INET_ATON( FROM_UNIXTIME( @@timestamp, ( TRIM( UNHEX(HEX('%m.%d.%Y') ) ) ) ) );
+
+CREATE TABLE t1 (d DATE);
+INSERT INTO t1 VALUES ('1989-03-10');
+SELECT TIME_FORMAT('23:59:43', BINARY d) AS f FROM t1 GROUP BY 'foo';
+DROP TABLE t1;
+
+CREATE TABLE t1 (d DATE) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('1900-01-01');
+SELECT LENGTH( DATE_FORMAT( d, BINARY DATABASE() ) ) AS f FROM t1 GROUP BY d;
+DROP TABLE t1;
+
+
--echo #
--echo # End of 10.1 tests
--echo #
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 83949f2502e..c10b6442ce8 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -455,7 +455,7 @@ err:
Create a formated date/time value in a string.
*/
-static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
+static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time,
timestamp_type type, MY_LOCALE *locale, String *str)
{
char intbuff[15];
@@ -469,7 +469,7 @@ static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
if (l_time->neg)
str->append('-');
- end= (ptr= format->format.str) + format->format.length;
+ end= (ptr= format.str) + format.length;
for (; ptr != end ; ptr++)
{
if (*ptr != '%' || ptr+1 == end)
@@ -1949,6 +1949,7 @@ uint Item_func_date_format::format_length(const String *format)
String *Item_func_date_format::val_str(String *str)
{
+ StringBuffer<64> format_buffer;
String *format;
MYSQL_TIME l_time;
uint size;
@@ -1958,7 +1959,7 @@ String *Item_func_date_format::val_str(String *str)
if (get_arg0_date(&l_time, is_time_flag))
return 0;
- if (!(format = args[1]->val_str(str)) || !format->length())
+ if (!(format= args[1]->val_str(&format_buffer)) || !format->length())
goto null_date;
if (fixed_length)
@@ -1969,18 +1970,13 @@ String *Item_func_date_format::val_str(String *str)
if (size < MAX_DATE_STRING_REP_LENGTH)
size= MAX_DATE_STRING_REP_LENGTH;
- if (format == str)
- str= &value; // Save result here
+ DBUG_ASSERT(format != str);
if (str->alloc(size))
goto null_date;
- DATE_TIME_FORMAT date_time_format;
- date_time_format.format.str= (char*) format->ptr();
- date_time_format.format.length= format->length();
-
/* Create the result string */
str->set_charset(collation.collation);
- if (!make_date_time(&date_time_format, &l_time,
+ if (!make_date_time(format->lex_cstring(), &l_time,
is_time_format ? MYSQL_TIMESTAMP_TIME :
MYSQL_TIMESTAMP_DATE,
locale, str))