diff options
author | bar@mysql.com <> | 2005-03-16 14:35:44 +0400 |
---|---|---|
committer | bar@mysql.com <> | 2005-03-16 14:35:44 +0400 |
commit | 2d8e8c02a5f4cd3874a238787ce6fcf3582dad41 (patch) | |
tree | debcee5802c88f5e81f7af034a0df15759df53b7 | |
parent | 515bd1fed851f88780daacca6beea3ff4fdff158 (diff) | |
parent | c6c887b99073d79d4da647bb2110d6ddb5af0d12 (diff) | |
download | mariadb-git-2d8e8c02a5f4cd3874a238787ce6fcf3582dad41.tar.gz |
Merge abarkov@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/usr/home/bar/mysql-4.1-bug8785
-rw-r--r-- | mysql-test/r/ctype_utf8.result | 7 | ||||
-rw-r--r-- | mysql-test/t/ctype_utf8.test | 9 | ||||
-rw-r--r-- | sql/item.cc | 12 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 3 | ||||
-rw-r--r-- | sql/sql_string.h | 4 |
5 files changed, 33 insertions, 2 deletions
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 13105e2276c..314567a1544 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -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 diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 35f2b2642be..2c498cd1922 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -695,6 +695,15 @@ 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 # select convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8); diff --git a/sql/item.cc b/sql/item.cc index 690ada2d660..2250bd9b32c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 54dd3b2d1b0..b4f75859469 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -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); } diff --git a/sql/sql_string.h b/sql/sql_string.h index 3ad4689cf36..8dff5558120 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -177,6 +177,10 @@ public: } } } + inline void shrink_to_length() + { + Alloced_length= str_length; + } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { |