From: Date: November 24 2005 1:49am Subject: bk commit into 5.0 tree (jimw:1.1977) BUG#14676 List-Archive: http://lists.mysql.com/internals/32627 X-Bug: 14676 Message-Id: <20051124004913.1B7C0A9296@rama.trainedmonkey.com> 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/23 16:49:07 jimw@stripped +3 -0 Fix possible corruption of results from SUBSTRING_INDEX(). (Bug #14676) sql/item_strfunc.cc 1.259 05/11/23 16:49:03 jimw@stripped +22 -16 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/23 16:49:03 jimw@stripped +8 -0 Add new test mysql-test/r/func_str.result 1.110 05/11/23 16:49:03 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-23 16:49:03 -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); @@ -1114,11 +1114,11 @@ #ifdef USE_MB if (use_mb(res->charset())) { - 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 *ptr= res->ptr(); + const char *strend= ptr+res->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-23 16:49:03 -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-23 16:49:03 -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