List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:July 14 2010 12:05pm
Subject:bzr commit into mysql-trunk branch (Georgi.Kodinov:3114)
View as plain text  
#At file:///home/kgeorge/mysql/work/B51876-trunk-merge/ based on revid:georgi.kodinov@stripped

 3114 Georgi Kodinov	2010-07-14 [merge]
      merge

    modified:
      mysql-test/r/loaddata.result
      mysql-test/t/loaddata.test
      sql/item_func.cc
      sql/sql_load.cc
=== modified file 'mysql-test/r/loaddata.result'
--- a/mysql-test/r/loaddata.result	2010-06-09 08:41:24 +0000
+++ b/mysql-test/r/loaddata.result	2010-07-14 12:05:20 +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: '?' for column 'a' at row 1
+Warning	1366	Incorrect integer value: '?' 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:41:24 +0000
+++ b/mysql-test/t/loaddata.test	2010-07-14 12:05:20 +0000
@@ -570,4 +570,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-05-14 05:28:51 +0000
+++ b/sql/item_func.cc	2010-07-14 12:05:20 +0000
@@ -5066,6 +5066,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;
@@ -5075,7 +5076,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:41:24 +0000
+++ b/sql/sql_load.cc	2010-07-14 12:05:20 +0000
@@ -1441,29 +1441,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)
@@ -1547,6 +1524,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-20100714120520-p3pqbx1ywi0y5mut.bundle
Thread
bzr commit into mysql-trunk branch (Georgi.Kodinov:3114) Georgi Kodinov14 Jul