summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbar@mysql.com <>2005-03-16 14:35:44 +0400
committerbar@mysql.com <>2005-03-16 14:35:44 +0400
commit2d8e8c02a5f4cd3874a238787ce6fcf3582dad41 (patch)
treedebcee5802c88f5e81f7af034a0df15759df53b7
parent515bd1fed851f88780daacca6beea3ff4fdff158 (diff)
parentc6c887b99073d79d4da647bb2110d6ddb5af0d12 (diff)
downloadmariadb-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.result7
-rw-r--r--mysql-test/t/ctype_utf8.test9
-rw-r--r--sql/item.cc12
-rw-r--r--sql/item_strfunc.cc3
-rw-r--r--sql/sql_string.h4
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)
{