List:Commits« Previous MessageNext Message »
From:Martin Hansson Date:December 15 2010 11:00am
Subject:bzr commit into mysql-5.1-bugteam branch (martin.hansson:3525) Bug#58165
View as plain text  
#At file:///data0/martin/bzrroot/bug58165/5.1bt/ based on revid:gleb.shchepa@stripped

 3525 Martin Hansson	2010-12-15
      Bug#58165: "my_empty_string" gets modified and causes LOAD DATA to fail and
      other crashes
      
      The string manipulating function insert() used a shared string buffer intended
      to always contain an empty string. Fixed by copying the buffer before
      modifying it.
      
      Relevant code has also been documented.

    modified:
      client/sql_string.cc
      mysql-test/r/func_str.result
      mysql-test/t/func_str.test
      sql/item_strfunc.cc
=== modified file 'client/sql_string.cc'
--- a/client/sql_string.cc	2010-07-09 12:00:17 +0000
+++ b/client/sql_string.cc	2010-12-15 11:00:25 +0000
@@ -58,11 +58,28 @@ bool String::real_alloc(uint32 arg_lengt
 }
 
 
-/*
-** Check that string is big enough. Set string[alloc_length] to 0
-** (for C functions)
-*/
+/**
+   Allocates a new buffer on the heap for this String.
+
+   - If the String's internal buffer is privately owned and heap allocated, a
+     new buffer will be allocated, data moved and the old buffer freed.
+
+   - If the String does not keep a private buffer on the heap, such a buffer
+     will be allocated and the string copied accoring to its length, as found
+     in String::length().
 
+   For C compatibility, the new string buffer is null terminated.
+
+   @param alloc_length The size of new buffer to be allocated, excluding null
+   terminator. If the current string buffer is larger than this value, no
+   allocation occurs.
+
+   @retval false Either the copy operation is complete or, if the size of the
+   new buffer is smaller than the currently allocated buffer (if one exists),
+   no allocation occured.
+
+   @retval true An error occured when attempting to allocate memory.
+*/
 bool String::realloc(uint32 alloc_length)
 {
   uint32 len=ALIGN_SIZE(alloc_length+1);
@@ -206,6 +223,17 @@ bool String::copy()
   return FALSE;
 }
 
+/**
+   Copies the internal buffer from str. If this String has a private heap
+   allocated buffer where new data does not fit, a new buffer is allocated
+   before copying and the old buffer freed. Character set information is also
+   copied.
+   
+   @param str The string whose internal buffer was duplicated.
+   
+   @retval false Success.
+   @retval true Memory allocation failed.
+ */
 bool String::copy(const String &str)
 {
   if (alloc(str.str_length))

=== modified file 'mysql-test/r/func_str.result'
--- a/mysql-test/r/func_str.result	2010-12-14 16:08:25 +0000
+++ b/mysql-test/r/func_str.result	2010-12-15 11:00:25 +0000
@@ -2612,4 +2612,20 @@ CONVERT(('' IN (REVERSE(CAST(('') AS DEC
 1
 Warnings:
 Warning	1292	Truncated incorrect DECIMAL value: ''
+# 
+# Bug#58165: "my_empty_string" gets modified and causes LOAD DATA to fail
+# and other crashes
+#
+CREATE TABLE t1 ( a TEXT );
+SELECT 'aaaaaaaaaaaaaa' INTO OUTFILE 'bug58165.txt';
+SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' );
+insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' )
+x
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: 'b'
+LOAD DATA INFILE 'bug58165.txt' INTO TABLE t1;
+SELECT * FROM t1;
+a
+aaaaaaaaaaaaaa
+DROP TABLE t1;
 End of 5.1 tests

=== modified file 'mysql-test/t/func_str.test'
--- a/mysql-test/t/func_str.test	2010-12-14 16:08:25 +0000
+++ b/mysql-test/t/func_str.test	2010-12-15 11:00:25 +0000
@@ -1369,4 +1369,15 @@ DROP TABLE t1;
 SELECT '1' IN ('1', SUBSTRING(-9223372036854775809, 1));
 SELECT CONVERT(('' IN (REVERSE(CAST(('') AS DECIMAL)), '')), CHAR(3));
 
+--echo # 
+--echo # Bug#58165: "my_empty_string" gets modified and causes LOAD DATA to fail
+--echo # and other crashes
+--echo #
+CREATE TABLE t1 ( a TEXT );
+SELECT 'aaaaaaaaaaaaaa' INTO OUTFILE 'bug58165.txt';
+SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' );
+LOAD DATA INFILE 'bug58165.txt' INTO TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
 --echo End of 5.1 tests

=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc	2010-10-12 19:28:03 +0000
+++ b/sql/item_strfunc.cc	2010-12-15 11:00:25 +0000
@@ -39,6 +39,12 @@ C_MODE_START
 #include "../mysys/my_static.h"			// For soundex_map
 C_MODE_END
 
+/*
+  This is an inherently dangerous design and should be abandoned. Our String
+  class does not support safely mutable strings. Functions that return
+  non-const String objects should either allocate buffers or use pre-allocated
+  ones.
+ */
 String my_empty_string("",default_charset_info);
 
 
@@ -1047,6 +1053,12 @@ String *Item_func_insert::val_str(String
     goto null;
   }
   res=copy_if_not_alloced(str,res,res->length());
+  /* This shows the dangers of returning my_empty_string. */
+  if (res == &my_empty_string)
+  {
+    str->copy("", 0, default_charset_info);
+    res= str;
+  }
   res->replace((uint32) start,(uint32) length,*res2);
   return res;
 null:


Attachment: [text/bzr-bundle] bzr/martin.hansson@oracle.com-20101215110025-vabuljud8s1t594x.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (martin.hansson:3525) Bug#58165Martin Hansson15 Dec