List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:July 14 2010 12:06pm
Subject:bzr push into mysql-5.1-bugteam branch (Georgi.Kodinov:3480 to 3481)
Bug#51876
View as plain text  
 3481 Georgi Kodinov	2010-07-14
      Bug #51876: crash/memory underrun when loading data with ucs2
      and reverse() function
            
      3 problems fixed : 
      1. The reported problem : caused by incorrect parsing of 
      the file as ucs data resulting in wrong length of the parsed
      string. Fixed by truncating the invalid trailing bytes 
      (non-complete multibyte characters) when reading from the file
      2. LOAD DATA when reading from a proper UCS2 file wasn't 
      recognizing the new line characters. Fixed by first looking 
      if a byte is a new line (or any other special) character before
      reading it as a part of a multibyte character.
      3. When using user variables to hold the column data in LOAD
      DATA the character set of the user variable was set incorrectly
      to the database charset. Fixed by setting it to the charset
      specified by LOAD DATA (if any). 

    modified:
      mysql-test/r/loaddata.result
      mysql-test/t/loaddata.test
      sql/item_func.cc
      sql/sql_load.cc
 3480 Georgi Kodinov	2010-07-14
      Bug #53493 : add_to_status does not handle the longlong fields in STATUS_VAR
      
      bytes_received/bytes_sent are ulonglong so they cannot be handled by the 
      ulong handling code in add_to_status/add_diff_to_status().
      
      Fixed by adding code to handle these two variables in 
      add_to_status()/add_diff_to_status() and making sure they are not a subject
      to the ulong handling code.

    modified:
      sql/sql_class.cc
      sql/sql_class.h
=== modified file 'mysql-test/r/loaddata.result'
--- a/mysql-test/r/loaddata.result	2010-06-09 08:29:27 +0000
+++ b/mysql-test/r/loaddata.result	2010-07-14 11:54:51 +0000
@@ -503,4 +503,33 @@ DROP TABLE t1;
 CREATE TABLE t1 (id INT NOT NULL);
 LOAD DATA LOCAL INFILE 'tb.txt' INTO TABLE t1;
 DROP TABLE t1;
+#
+# Bug #51876 : crash/memory underrun when loading data with ucs2 
+#   and reverse() function
+#
+# Problem # 1 (original report): wrong parsing of ucs2 data
+SELECT '00' UNION SELECT '10' INTO OUTFILE 'tmpp.txt';
+CREATE TABLE t1(a INT);
+LOAD DATA INFILE 'tmpp.txt' INTO TABLE t1 CHARACTER SET ucs2
+(@b) SET a=REVERSE(@b);
+Warnings:
+Warning	1366	Incorrect integer value: '00' for column 'a' at row 1
+Warning	1366	Incorrect integer value: '10' for column 'a' at row 2
+# should return 2 zeroes (as the value is truncated)
+SELECT * FROM t1;
+a
+0
+0
+DROP TABLE t1;
+# Problem # 2 : if you write and read ucs2 data to a file they're lost
+SELECT '00' UNION SELECT '10' INTO OUTFILE 'tmpp2.txt' CHARACTER SET ucs2;
+CREATE TABLE t1(a INT);
+LOAD DATA INFILE 'tmpp2.txt' INTO TABLE t1 CHARACTER SET ucs2
+(@b) SET a=REVERSE(@b);
+# should return 0 and 1 (10 reversed)
+SELECT * FROM t1;
+a
+0
+1
+DROP TABLE t1;
 End of 5.1 tests

=== modified file 'mysql-test/t/loaddata.test'
--- a/mysql-test/t/loaddata.test	2010-06-09 08:29:27 +0000
+++ b/mysql-test/t/loaddata.test	2010-07-14 11:54:51 +0000
@@ -580,4 +580,36 @@ DROP TABLE t1;
 connection default;
 disconnect con1;
 
+
+--echo #
+--echo # Bug #51876 : crash/memory underrun when loading data with ucs2 
+--echo #   and reverse() function
+--echo #
+
+--echo # Problem # 1 (original report): wrong parsing of ucs2 data
+SELECT '00' UNION SELECT '10' INTO OUTFILE 'tmpp.txt';
+CREATE TABLE t1(a INT);
+LOAD DATA INFILE 'tmpp.txt' INTO TABLE t1 CHARACTER SET ucs2
+(@b) SET a=REVERSE(@b);
+--echo # should return 2 zeroes (as the value is truncated)
+SELECT * FROM t1;
+
+DROP TABLE t1;
+let $MYSQLD_DATADIR= `select @@datadir`;
+remove_file $MYSQLD_DATADIR/test/tmpp.txt;
+
+
+--echo # Problem # 2 : if you write and read ucs2 data to a file they're lost
+SELECT '00' UNION SELECT '10' INTO OUTFILE 'tmpp2.txt' CHARACTER SET ucs2;
+CREATE TABLE t1(a INT);
+LOAD DATA INFILE 'tmpp2.txt' INTO TABLE t1 CHARACTER SET ucs2
+(@b) SET a=REVERSE(@b);
+--echo # should return 0 and 1 (10 reversed)
+SELECT * FROM t1;
+
+DROP TABLE t1;
+let $MYSQLD_DATADIR= `select @@datadir`;
+remove_file $MYSQLD_DATADIR/test/tmpp2.txt;
+
+
 --echo End of 5.1 tests

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2010-03-19 09:06:40 +0000
+++ b/sql/item_func.cc	2010-07-14 11:54:51 +0000
@@ -4715,6 +4715,7 @@ bool Item_func_get_user_var::set_value(T
 bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
 {
   DBUG_ASSERT(fixed == 0);
+  DBUG_ASSERT(thd->lex->exchange);
   if (Item::fix_fields(thd, ref) ||
       !(entry= get_variable(&thd->user_vars, name, 1)))
     return TRUE;
@@ -4724,7 +4725,9 @@ bool Item_user_var_as_out_param::fix_fie
     of fields in LOAD DATA INFILE.
     (Since Item_user_var_as_out_param is used only there).
   */
-  entry->collation.set(thd->variables.collation_database);
+  entry->collation.set(thd->lex->exchange->cs ? 
+                       thd->lex->exchange->cs :
+                       thd->variables.collation_database);
   entry->update_query_id= thd->query_id;
   return FALSE;
 }

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2010-06-09 08:29:27 +0000
+++ b/sql/sql_load.cc	2010-07-14 11:54:51 +0000
@@ -1208,29 +1208,6 @@ int READ_INFO::read_field()
     while ( to < end_of_buff)
     {
       chr = GET;
-#ifdef USE_MB
-      if ((my_mbcharlen(read_charset, chr) > 1) &&
-          to+my_mbcharlen(read_charset, chr) <= end_of_buff)
-      {
-	  uchar* p = (uchar*)to;
-	  *to++ = chr;
-	  int ml = my_mbcharlen(read_charset, chr);
-	  int i;
-	  for (i=1; i<ml; i++) {
-	      chr = GET;
-	      if (chr == my_b_EOF)
-		  goto found_eof;
-	      *to++ = chr;
-	  }
-	  if (my_ismbchar(read_charset,
-                          (const char *)p,
-                          (const char *)to))
-	    continue;
-	  for (i=0; i<ml; i++)
-	    PUSH((uchar) *--to);
-	  chr = GET;
-      }
-#endif
       if (chr == my_b_EOF)
 	goto found_eof;
       if (chr == escape_char)
@@ -1314,6 +1291,39 @@ int READ_INFO::read_field()
 	  return 0;
 	}
       }
+#ifdef USE_MB
+      if (my_mbcharlen(read_charset, chr) > 1 &&
+          to + my_mbcharlen(read_charset, chr) <= end_of_buff)
+      {
+        uchar* p= (uchar*) to;
+        int ml, i;
+        *to++ = chr;
+
+        ml= my_mbcharlen(read_charset, chr);
+
+        for (i= 1; i < ml; i++) 
+        {
+          chr= GET;
+          if (chr == my_b_EOF)
+          {
+            /*
+             Need to back up the bytes already ready from illformed
+             multi-byte char 
+            */
+            to-= i;
+            goto found_eof;
+          }
+          *to++ = chr;
+        }
+        if (my_ismbchar(read_charset,
+                        (const char *)p,
+                        (const char *)to))
+          continue;
+        for (i= 0; i < ml; i++)
+          PUSH((uchar) *--to);
+        chr= GET;
+      }
+#endif
       *to++ = (uchar) chr;
     }
     /*


Attachment: [text/bzr-bundle] bzr/georgi.kodinov@oracle.com-20100714115451-a0bllllpoyaxfn4b.bundle
Thread
bzr push into mysql-5.1-bugteam branch (Georgi.Kodinov:3480 to 3481)Bug#51876Georgi Kodinov14 Jul