Commit 8aaacc91 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-3987 uninitialized read in Item_cond::fix_fields leads to crash: select...

MDEV-3987 uninitialized read in Item_cond::fix_fields leads to crash: select .. where .. in ( select ... )

change Item_func_group_concat to use max_length according to the expected semantics
parent 78d9fdb1
...@@ -1086,3 +1086,8 @@ ERROR HY000: Row 3 was cut by GROUP_CONCAT() ...@@ -1086,3 +1086,8 @@ ERROR HY000: Row 3 was cut by GROUP_CONCAT()
SET group_concat_max_len = DEFAULT; SET group_concat_max_len = DEFAULT;
SET @@sql_mode = @old_sql_mode; SET @@sql_mode = @old_sql_mode;
DROP TABLE t1, t2; DROP TABLE t1, t2;
create table t1 (a char(1) character set utf8);
insert into t1 values ('a'),('b');
select 1 from t1 where a in (select group_concat(a) from t1);
1
drop table t1;
...@@ -795,3 +795,11 @@ INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b; ...@@ -795,3 +795,11 @@ INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b;
SET group_concat_max_len = DEFAULT; SET group_concat_max_len = DEFAULT;
SET @@sql_mode = @old_sql_mode; SET @@sql_mode = @old_sql_mode;
DROP TABLE t1, t2; DROP TABLE t1, t2;
#
# MDEV-3987 uninitialized read in Item_cond::fix_fields leads to crash: select .. where .. in ( select ... )
#
create table t1 (a char(1) character set utf8);
insert into t1 values ('a'),('b');
select 1 from t1 where a in (select group_concat(a) from t1);
drop table t1;
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define SQL_ITEM_INCLUDED #define SQL_ITEM_INCLUDED
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. /* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
Copyright (c) 2009-2011 Monty Program Ab Copyright (c) 2009, 2013 Monty Program Ab
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -611,7 +611,11 @@ public: ...@@ -611,7 +611,11 @@ public:
@see Query_arena::free_list @see Query_arena::free_list
*/ */
Item *next; Item *next;
uint32 max_length; /* Maximum length, in bytes */ /*
The maximum value length in characters multiplied by collation->mbmaxlen.
Almost always it's the maximum value length in bytes.
*/
uint32 max_length;
/* /*
TODO: convert name and name_length fields into LEX_STRING to keep them in TODO: convert name and name_length fields into LEX_STRING to keep them in
sync (see bug #11829681/60295 etc). Then also remove some strlen(name) sync (see bug #11829681/60295 etc). Then also remove some strlen(name)
......
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. /* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
Copyright (c) 2008-2011 Monty Program Ab Copyright (c) 2008, 2013 Monty Program Ab
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -2986,6 +2986,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), ...@@ -2986,6 +2986,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
{ {
Item_func_group_concat *item= (Item_func_group_concat *) item_arg; Item_func_group_concat *item= (Item_func_group_concat *) item_arg;
TABLE *table= item->table; TABLE *table= item->table;
uint max_length= table->in_use->variables.group_concat_max_len;
String tmp((char *)table->record[1], table->s->reclength, String tmp((char *)table->record[1], table->s->reclength,
default_charset_info); default_charset_info);
String tmp2; String tmp2;
...@@ -3028,7 +3029,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), ...@@ -3028,7 +3029,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
item->row_count++; item->row_count++;
/* stop if length of result more than max_length */ /* stop if length of result more than max_length */
if (result->length() > item->max_length) if (result->length() > max_length)
{ {
int well_formed_error; int well_formed_error;
CHARSET_INFO *cs= item->collation.collation; CHARSET_INFO *cs= item->collation.collation;
...@@ -3041,7 +3042,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), ...@@ -3041,7 +3042,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
*/ */
add_length= cs->cset->well_formed_len(cs, add_length= cs->cset->well_formed_len(cs,
ptr + old_length, ptr + old_length,
ptr + item->max_length, ptr + max_length,
result->length(), result->length(),
&well_formed_error); &well_formed_error);
result->length(old_length + add_length); result->length(old_length + add_length);
...@@ -3205,19 +3206,11 @@ Field *Item_func_group_concat::make_string_field(TABLE *table) ...@@ -3205,19 +3206,11 @@ Field *Item_func_group_concat::make_string_field(TABLE *table)
{ {
Field *field; Field *field;
DBUG_ASSERT(collation.collation); DBUG_ASSERT(collation.collation);
/* if (too_big_for_varchar())
max_characters is maximum number of characters field= new Field_blob(max_length,
what can fit into max_length size. It's necessary
to use field size what allows to store group_concat
result without truncation. For this purpose we use
max_characters * CS->mbmaxlen.
*/
const uint32 max_characters= max_length / collation.collation->mbminlen;
if (max_characters > CONVERT_IF_BIGGER_TO_BLOB)
field= new Field_blob(max_characters * collation.collation->mbmaxlen,
maybe_null, name, collation.collation, TRUE); maybe_null, name, collation.collation, TRUE);
else else
field= new Field_varstring(max_characters * collation.collation->mbmaxlen, field= new Field_varstring(max_length,
maybe_null, name, table->s, collation.collation); maybe_null, name, table->s, collation.collation);
if (field) if (field)
...@@ -3332,7 +3325,9 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) ...@@ -3332,7 +3325,9 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
result.set_charset(collation.collation); result.set_charset(collation.collation);
result_field= 0; result_field= 0;
null_value= 1; null_value= 1;
max_length= thd->variables.group_concat_max_len; max_length= thd->variables.group_concat_max_len
/ collation.collation->mbminlen
* collation.collation->mbmaxlen;
uint32 offset; uint32 offset;
if (separator->needs_conversion(separator->length(), separator->charset(), if (separator->needs_conversion(separator->length(), separator->charset(),
......
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