MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Tatiana A. Nurnberg Date:November 20 2008 2:39pm
Subject:bzr commit into mysql-5.0-bugteam branch (azundris:2719) Bug#39591
View as plain text  
#At file:///misc/mysql/forest/39591v2/50-39591v2/

 2719 Tatiana A. Nurnberg	2008-11-20
      Bug#39591: Crash if table comment is longer than 62 characters
      
      It was possible to crash a mysqld build with EXTRA_DEBUG using
      CREATE TABLE ... COMMENT with a specially-crafted UTF-8 string.
      
      This CS removes the check that caused it since it no longer
      applies in current servers anyway, and adds comments instead
      to avoid future confusion. 
modified:
  mysql-test/r/strict.result
  mysql-test/t/strict.test
  sql/unireg.cc

per-file messages:
  mysql-test/r/strict.result
    Try to crash mysqld with a "suitable" multi-byte (3-byte UTF-8) string
    for a table comment.
  mysql-test/t/strict.test
    Try to crash mysqld with a "suitable" multi-byte (3-byte UTF-8) string
    for a table comment.
  sql/unireg.cc
    Talk at length about limits in .frm form-info, characters vs bytes,
    inlined vs extra-segement TABLE-COMMENTS, and the differences in
    6.0+ vs <6.0 when it comes to UTF-8.
    
    Also, remove a check that no longer applies and that could lead to
    problems in pathological cases.
=== modified file 'mysql-test/r/strict.result'
--- a/mysql-test/r/strict.result	2008-05-06 16:43:46 +0000
+++ b/mysql-test/r/strict.result	2008-11-20 14:39:39 +0000
@@ -1348,6 +1348,13 @@ t1	CREATE TABLE `t1` (
   `i` int(11) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='123456789*123456789*123456789*123456789*123456789*123456789*'
 drop table t1;
+CREATE TABLE t3 (f1 INT) COMMENT 'כקבהחןכקבהחןכקבהחןכקבהחןכק×ןכקבהחןכקבהחןכe Table
+t3	CREATE TABLE `t3` (
+  `f1` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='כקבהחןכקבהחןכקבŸ×›×§×‘החןכקבהחןכ×חן'
+DROP TABLE t3;
 set sql_mode= 'traditional';
 create table t1(col1 tinyint, col2 tinyint unsigned, 
 col3 smallint, col4 smallint unsigned,

=== modified file 'mysql-test/t/strict.test'
--- a/mysql-test/t/strict.test	2007-06-01 22:57:25 +0000
+++ b/mysql-test/t/strict.test	2008-11-20 14:39:39 +0000
@@ -1200,6 +1200,15 @@ show create table t1;
 drop table t1;
 
 #
+# Bug #39591: Crash if table comment is longer than 62 characters
+#
+
+#60 chars, 120 (+1) bytes (UTF-8 with 2-byte chars)
+CREATE TABLE t3 (f1 INT) COMMENT 'כקבהחןכק—ןכקבהחןכקבהחן×החןכקבהחן';
+SHOW CREATE TABLE t3;
+DROP TABLE t3;
+
+#
 # Bug #26359: Strings becoming truncated and converted to numbers under STRICT mode
 #
 set sql_mode= 'traditional';

=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc	2007-12-17 08:45:36 +0000
+++ b/sql/unireg.cc	2008-11-20 14:39:39 +0000
@@ -143,6 +143,24 @@ bool mysql_create_frm(THD *thd, my_strin
 			     (create_info->min_rows == 1) && (keys == 0));
   int2store(fileinfo+28,key_info_length);
 
+  /*
+    This gives us the byte-position of the character at
+    (character-position, not byte-position) TABLE_COMMENT_MAXLEN.
+    The trick here is that character-positions start at 0, so the last
+    character in a maximum-allowed length string would be at char-pos
+    MAXLEN-1; charpos MAXLEN will be the position of the terminator.
+    Consequently, bytepos(charpos(MAXLEN)) should be equal to
+    comment[length] (which should also be the terminator, or at least
+    the first byte after the payload in the strict sense). If this is
+    not so (bytepos(charpos(MAXLEN)) comes /before/ the end of the
+    string), the string is too long.
+
+    For additional credit, realise that UTF-8 has 1-3 bytes before 6.0,
+    and 1-4 bytes in 6.0 (6.0 also has UTF-32). This means that the
+    inlined COMMENT supposedly does not exceed 60 character plus
+    terminator, vulgo, 181 bytes.
+  */
+
   tmp_len= system_charset_info->cset->charpos(system_charset_info,
                                               create_info->comment.str,
                                               create_info->comment.str +
@@ -165,14 +183,6 @@ bool mysql_create_frm(THD *thd, my_strin
   strmake((char*) forminfo+47, create_info->comment.str ?
           create_info->comment.str : "", create_info->comment.length);
   forminfo[46]=(uchar) create_info->comment.length;
-#ifdef EXTRA_DEBUG
-  /*
-    EXTRA_DEBUG causes strmake() to initialize its buffer behind the
-    payload with a magic value to detect wrong buffer-sizes. We
-    explicitly zero that segment again.
-  */
-  memset((char*) forminfo+47 + forminfo[46], 0, 61 - forminfo[46]);
-#endif
   if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) ||
       my_pwrite(file,(byte*) keybuff,key_info_length,
 		(ulong) uint2korr(fileinfo+6),MYF_RW))

Thread
bzr commit into mysql-5.0-bugteam branch (azundris:2719) Bug#39591Tatiana A. Nurnberg20 Nov