diff options
author | unknown <bar@mysql.com> | 2005-03-15 17:15:47 +0400 |
---|---|---|
committer | unknown <bar@mysql.com> | 2005-03-15 17:15:47 +0400 |
commit | c703954578ce3c806112bbc2319988fc289ab8a1 (patch) | |
tree | 7c2353f000f6d7f885619924e485c5b62d93c768 /sql | |
parent | be26b499695adfb6c02f0131e0016613433cc28c (diff) | |
download | mariadb-git-c703954578ce3c806112bbc2319988fc289ab8a1.tar.gz |
# Bug#8785 Problem with nested concats and
character set conversion of a string constant.
mysql-test/r/ctype_utf8.result:
Adding test
mysql-test/t/ctype_utf8.test:
Addign test
sql/item_strfunc.cc:
Remove previous fix: it was not 100% correct.
A non const_item() can return a constant String.
sql/sql_string.h:
A new method to cut Alloced_length to str_length for
string constants, to avoid reusing them as a buffer
in things like CONCAT().
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 12 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 3 | ||||
-rw-r--r-- | sql/sql_string.h | 4 |
3 files changed, 17 insertions, 2 deletions
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) { |