Loading mysql-test/r/ctype_utf8.result +7 −0 Original line number Diff line number Diff line Loading @@ -861,6 +861,13 @@ user c one <one> two <two> DROP TABLE t1; create table t1 (f1 varchar(1) not null) default charset utf8; insert into t1 values (''), (''); select concat(concat(_latin1'->',f1),_latin1'<-') from t1; concat(concat(_latin1'->',f1),_latin1'<-') -><- -><- drop table t1; select convert(_koi8r'' using utf8) < convert(_koi8r'' using utf8); convert(_koi8r'' using utf8) < convert(_koi8r'' using utf8) 1 mysql-test/t/ctype_utf8.test +9 −0 Original line number Diff line number Diff line Loading @@ -694,6 +694,15 @@ SELECT CHARSET('a'); SELECT user, CONCAT('<', user, '>') AS c FROM t1; DROP TABLE t1; # # Bug#8785 # the same problem with the above, but with nested CONCATs # create table t1 (f1 varchar(1) not null) default charset utf8; insert into t1 values (''), (''); select concat(concat(_latin1'->',f1),_latin1'<-') from t1; drop table t1; # # Bug#8385: utf8_general_ci treats Cyrillic letters I and SHORT I as the same # Loading sql/item.cc +12 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,18 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); /* The above line executes str_value.realloc() internally, which alligns Alloced_length using ALLIGN_SIZE. In the case of Item_string::str_value we don't want Alloced_length to be longer than str_length. Otherwise, some functions like Item_func_concat::val_str() try to reuse str_value as a buffer for concatenation result for optimization purposes, so our string constant become corrupted. See bug#8785 for more details. Let's shrink Alloced_length to str_length to avoid this problem. */ conv->str_value.shrink_to_length(); return conv; } Loading sql/item_strfunc.cc +1 −2 Original line number Diff line number Diff line Loading @@ -277,8 +277,7 @@ String *Item_func_concat::val_str(String *str) current_thd->variables.max_allowed_packet); goto null; } if (!args[0]->const_item() && res->alloced_length() >= res->length()+res2->length()) if (res->alloced_length() >= res->length()+res2->length()) { // Use old buffer res->append(*res2); } Loading sql/sql_string.h +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ class String } } } inline void shrink_to_length() { Alloced_length= str_length; } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { Loading Loading
mysql-test/r/ctype_utf8.result +7 −0 Original line number Diff line number Diff line Loading @@ -861,6 +861,13 @@ user c one <one> two <two> DROP TABLE t1; create table t1 (f1 varchar(1) not null) default charset utf8; insert into t1 values (''), (''); select concat(concat(_latin1'->',f1),_latin1'<-') from t1; concat(concat(_latin1'->',f1),_latin1'<-') -><- -><- drop table t1; select convert(_koi8r'' using utf8) < convert(_koi8r'' using utf8); convert(_koi8r'' using utf8) < convert(_koi8r'' using utf8) 1
mysql-test/t/ctype_utf8.test +9 −0 Original line number Diff line number Diff line Loading @@ -694,6 +694,15 @@ SELECT CHARSET('a'); SELECT user, CONCAT('<', user, '>') AS c FROM t1; DROP TABLE t1; # # Bug#8785 # the same problem with the above, but with nested CONCATs # create table t1 (f1 varchar(1) not null) default charset utf8; insert into t1 values (''), (''); select concat(concat(_latin1'->',f1),_latin1'<-') from t1; drop table t1; # # Bug#8385: utf8_general_ci treats Cyrillic letters I and SHORT I as the same # Loading
sql/item.cc +12 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,18 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); /* The above line executes str_value.realloc() internally, which alligns Alloced_length using ALLIGN_SIZE. In the case of Item_string::str_value we don't want Alloced_length to be longer than str_length. Otherwise, some functions like Item_func_concat::val_str() try to reuse str_value as a buffer for concatenation result for optimization purposes, so our string constant become corrupted. See bug#8785 for more details. Let's shrink Alloced_length to str_length to avoid this problem. */ conv->str_value.shrink_to_length(); return conv; } Loading
sql/item_strfunc.cc +1 −2 Original line number Diff line number Diff line Loading @@ -277,8 +277,7 @@ String *Item_func_concat::val_str(String *str) current_thd->variables.max_allowed_packet); goto null; } if (!args[0]->const_item() && res->alloced_length() >= res->length()+res2->length()) if (res->alloced_length() >= res->length()+res2->length()) { // Use old buffer res->append(*res2); } Loading
sql/sql_string.h +4 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,10 @@ class String } } } inline void shrink_to_length() { Alloced_length= str_length; } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { Loading