List:Internals« Previous MessageNext Message »
From:Jim Winstead Date:November 9 2005 2:16am
Subject:bk commit into 5.0 tree (jimw:1.1977) BUG#14676
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of jimw. When jimw does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1977 05/11/08 17:16:34 jimw@stripped +3 -0
  Fix possible corruption of results from SUBSTRING_INDEX(). (Bug #14676)

  sql/item_strfunc.cc
    1.259 05/11/08 17:16:30 jimw@stripped +20 -14
    Mark tmp_value in Item_func_substr_index as const so that we don't
    overwrite the contents of another String when getting the delimiter.
    Fix typo in variable names (delimeter -> delimiter).

  mysql-test/t/func_str.test
    1.84 05/11/08 17:16:30 jimw@stripped +8 -0
    Add new test

  mysql-test/r/func_str.result
    1.110 05/11/08 17:16:30 jimw@stripped +7 -0
    Add new results

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	jimw
# Host:	rama.(none)
# Root:	/home/jimw/my/mysql-5.0-14676

--- 1.258/sql/item_strfunc.cc	2005-10-13 03:09:35 -07:00
+++ 1.259/sql/item_strfunc.cc	2005-11-08 17:16:30 -08:00
@@ -1094,9 +1094,9 @@
 String *Item_func_substr_index::val_str(String *str)
 {
   DBUG_ASSERT(fixed == 1);
-  String *res =args[0]->val_str(str);
-  String *delimeter =args[1]->val_str(&tmp_value);
-  int32 count = (int32) args[2]->val_int();
+  String *res= args[0]->val_str(str);
+  String *delimiter= args[1]->val_str(&tmp_value);
+  int32 count= (int32) args[2]->val_int();
   uint offset;
 
   if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
@@ -1105,8 +1105,8 @@
     return 0;
   }
   null_value=0;
-  uint delimeter_length=delimeter->length();
-  if (!res->length() || !delimeter_length || !count)
+  uint delimiter_length=delimiter->length();
+  if (!res->length() || !delimiter_length || !count)
     return &my_empty_string;		// Wrong parameters
 
   res->set_charset(collation.collation);
@@ -1116,9 +1116,9 @@
   {
     const char *ptr=res->ptr();
     const char *strend = ptr+res->length();
-    const char *end=strend-delimeter_length+1;
-    const char *search=delimeter->ptr();
-    const char *search_end=search+delimeter_length;
+    const char *end=strend-delimiter_length+1;
+    const char *search=delimiter->ptr();
+    const char *search_end=search+delimiter_length;
     int32 n=0,c=count,pass;
     register uint32 l;
     for (pass=(count>0);pass<2;++pass)
@@ -1133,7 +1133,7 @@
 	    if (*i++ != *j++) goto skip;
 	  if (pass==0) ++n;
 	  else if (!--c) break;
-	  ptr+=delimeter_length;
+	  ptr+=delimiter_length;
 	  continue;
 	}
     skip:
@@ -1155,7 +1155,7 @@
         }
         else /* return right part */
         {
-	  ptr+=delimeter_length;
+	  ptr+=delimiter_length;
 	  tmp_value.set(*res,(ulong) (ptr-res->ptr()), (ulong) (strend-ptr));
         }
       }
@@ -1166,9 +1166,9 @@
   {
     if (count > 0)
     {					// start counting from the beginning
-      for (offset=0 ;; offset+=delimeter_length)
+      for (offset=0 ;; offset+=delimiter_length)
       {
-	if ((int) (offset=res->strstr(*delimeter,offset)) < 0)
+	if ((int) (offset=res->strstr(*delimiter,offset)) < 0)
 	  return res;			// Didn't find, return org string
 	if (!--count)
 	{
@@ -1189,7 +1189,7 @@
           address space less than where the found substring is located
           in res
         */
-	if ((int) (offset=res->strrstr(*delimeter,offset)) < 0)
+	if ((int) (offset=res->strrstr(*delimiter,offset)) < 0)
 	  return res;			// Didn't find, return org string
         /*
           At this point, we've searched for the substring
@@ -1197,13 +1197,19 @@
         */
 	if (!++count)
 	{
-	  offset+=delimeter_length;
+	  offset+=delimiter_length;
 	  tmp_value.set(*res,offset,res->length()- offset);
 	  break;
 	}
       }
     }
   }
+  /*
+    We always mark tmp_value as const so that if val_str() is called again
+    on this object, we don't disrupt the contents of tmp_value when it was
+    derived from another String.
+  */
+  tmp_value.mark_as_const();
   return (&tmp_value);
 }
 

--- 1.109/mysql-test/r/func_str.result	2005-10-11 14:58:17 -07:00
+++ 1.110/mysql-test/r/func_str.result	2005-11-08 17:16:30 -08:00
@@ -1023,3 +1023,10 @@
 format(d, 2)
 NULL
 drop table t1;
+create table t1 (c varchar(40));
+insert into t1 values ('y,abc'),('y,abc');
+select c, substring_index(lcase(c), @q:=',', -1) as res from t1;
+c	res
+y,abc	abc
+y,abc	abc
+drop table t1;

--- 1.83/mysql-test/t/func_str.test	2005-10-11 14:58:17 -07:00
+++ 1.84/mysql-test/t/func_str.test	2005-11-08 17:16:30 -08:00
@@ -676,4 +676,12 @@
 select format(d, 2) from t1;
 drop table t1;
 
+#
+# Bug #14676: substring_index() returns incorrect results
+#
+create table t1 (c varchar(40));
+insert into t1 values ('y,abc'),('y,abc');
+select c, substring_index(lcase(c), @q:=',', -1) as res from t1;
+drop table t1;
+
 # End of 5.0 tests
Thread
bk commit into 5.0 tree (jimw:1.1977) BUG#14676Jim Winstead9 Nov