[Commits] cec8f1b: MDEV-7055: MySQL#74664 - InnoDB: Failing assertion: len <= col->len || col->mtype == 5 || (col->len == 0 && col->mtype == 1) in file rem0rec.cc line 845

Jan Lindström jan.lindstrom at mariadb.com
Tue Dec 8 08:53:33 EET 2015


revision-id: cec8f1b3268b1f34007c56e4dcc3d226dc41a25c (mariadb-5.5.46-17-gcec8f1b)
parent(s): 0df22a539e046a9090a99f10260cf6d80f0c4e26
committer: Jan Lindström
timestamp: 2015-12-08 08:47:54 +0200
message:

MDEV-7055: MySQL#74664 - InnoDB: Failing assertion: len <= col->len || col->mtype == 5 || (col->len == 0 && col->mtype == 1) in file rem0rec.cc line 845

Assertion is result of incorrect parameters passed on handler::write_row()
because date_format result string size and format was incorrectly handled
when client connection charset was ucs2. In ucs2 all characters are
represented by two bytes, e.g. '%W' is represented as "\0%\0W".
When reading format most significant bytes from format specifiers
should be ignored.

---
 mysql-test/r/date-format-ctype.result | 60 +++++++++++++++++++++++++++++++++++
 mysql-test/t/date-format-ctype.test   | 32 +++++++++++++++++++
 sql/item_timefunc.cc                  |  8 +++++
 3 files changed, 100 insertions(+)

diff --git a/mysql-test/r/date-format-ctype.result b/mysql-test/r/date-format-ctype.result
new file mode 100644
index 0000000..bfdaa59
--- /dev/null
+++ b/mysql-test/r/date-format-ctype.result
@@ -0,0 +1,60 @@
+set character_set_connection=ucs2;
+set default_storage_engine=MyISAM;
+SELECT date_format('2001-01-01','%W');
+date_format('2001-01-01','%W')
+Monday
+SELECT date_format('2001-01-01','%W rubb ish %w');
+date_format('2001-01-01','%W rubb ish %w')
+Monday rubb ish 1
+SELECT date_format('2001-01-01','%W rubb ish %');
+date_format('2001-01-01','%W rubb ish %')
+Monday rubb ish %
+CREATE TABLE t1 SELECT if(0=0,'Y','N');
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+Warnings:
+Warning	1265	Data truncated for column 'if(0=0,'Y','N')' at row 1
+SELECT * FROM t1;
+if(0=0,'Y','N')
+Y
+M
+set character_set_connection=utf8;
+select date_format('2001-01-01','%W');
+date_format('2001-01-01','%W')
+Monday
+SELECT date_format('2001-01-01','%W rubb ish %w');
+date_format('2001-01-01','%W rubb ish %w')
+Monday rubb ish 1
+SELECT date_format('2001-01-01','%W rubb ish %');
+date_format('2001-01-01','%W rubb ish %')
+Monday rubb ish %
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+Warnings:
+Warning	1265	Data truncated for column 'if(0=0,'Y','N')' at row 1
+SELECT * FROM t1;
+if(0=0,'Y','N')
+Y
+M
+M
+DROP TABLE t1;
+set character_set_connection=ucs2;
+set default_storage_engine=InnoDB;
+CREATE TABLE t1 SELECT if(0=0,'Y','N');
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+Warnings:
+Warning	1265	Data truncated for column 'if(0=0,'Y','N')' at row 1
+SELECT * FROM t1;
+if(0=0,'Y','N')
+Y
+M
+set character_set_connection=utf8;
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+Warnings:
+Warning	1265	Data truncated for column 'if(0=0,'Y','N')' at row 1
+SELECT * FROM t1;
+if(0=0,'Y','N')
+Y
+M
+M
+DROP TABLE t1;
+set character_set_connection=default;
+set default_storage_engine=default;
diff --git a/mysql-test/t/date-format-ctype.test b/mysql-test/t/date-format-ctype.test
new file mode 100644
index 0000000..9fdfe93
--- /dev/null
+++ b/mysql-test/t/date-format-ctype.test
@@ -0,0 +1,32 @@
+-- source include/have_innodb.inc
+
+#
+# MDEV-7055: MySQL#74664 - InnoDB: Failing assertion: len <= col->len || col->mtype == 5 || (col->len == 0 && col->mtype == 1) in file rem0rec.cc line 845
+#
+
+set character_set_connection=ucs2;
+set default_storage_engine=MyISAM;
+SELECT date_format('2001-01-01','%W');
+SELECT date_format('2001-01-01','%W rubb ish %w');
+SELECT date_format('2001-01-01','%W rubb ish %');
+CREATE TABLE t1 SELECT if(0=0,'Y','N');
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+SELECT * FROM t1;
+set character_set_connection=utf8;
+select date_format('2001-01-01','%W');
+SELECT date_format('2001-01-01','%W rubb ish %w');
+SELECT date_format('2001-01-01','%W rubb ish %');
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+SELECT * FROM t1;
+DROP TABLE t1;
+set character_set_connection=ucs2;
+set default_storage_engine=InnoDB;
+CREATE TABLE t1 SELECT if(0=0,'Y','N');
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+SELECT * FROM t1;
+set character_set_connection=utf8;
+INSERT INTO t1 VALUES(date_format('2001-01-01','%W'));
+SELECT * FROM t1;
+DROP TABLE t1;
+set character_set_connection=default;
+set default_storage_engine=default;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 522004e..b66ca15 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -467,10 +467,15 @@ static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
   end= (ptr= format->format.str) + format->format.length;
   for (; ptr != end ; ptr++)
   {
+    if (ptr != end-2 && *ptr == '\0' && *(ptr+1) == '%')
+      ptr++; /* skip ucs2 most significant byte */
     if (*ptr != '%' || ptr+1 == end)
       str->append(*ptr);
     else
     {
+      if(ptr != end-2 && *(ptr+1) == '\0')
+        ptr++; /* skip '%' character and below ucs2 most significant byte */
+
       switch (*++ptr) {
       case 'M':
         if (!l_time->month)
@@ -1791,6 +1796,9 @@ uint Item_func_date_format::format_length(const String *format)
       size++;
     else
     {
+      if(ptr != end-2 && *(ptr+1) == '\0')
+        ptr++; /* skip '%' character and below ucs2 most significant byte */
+
       switch(*++ptr) {
       case 'M': /* month, textual */
       case 'W': /* day (of the week), textual */


More information about the commits mailing list