Commit c7039545 authored by unknown's avatar unknown

# 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().
parent be26b499
......@@ -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
......@@ -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
#
......
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -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)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment