summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bar@mysql.com>2005-03-15 17:15:47 +0400
committerunknown <bar@mysql.com>2005-03-15 17:15:47 +0400
commitc703954578ce3c806112bbc2319988fc289ab8a1 (patch)
tree7c2353f000f6d7f885619924e485c5b62d93c768 /sql
parentbe26b499695adfb6c02f0131e0016613433cc28c (diff)
downloadmariadb-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.cc12
-rw-r--r--sql/item_strfunc.cc3
-rw-r--r--sql/sql_string.h4
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)
{