Commit 00fff1e1 authored by Chaithra Gopalareddy's avatar Chaithra Gopalareddy

Bug #14099846: EXPORT_SET CRASHES DUE TO OVERALLOCATION OF MEMORY

Backport the fix from 5.6 to 5.1
Base bug number : 11765562
parent e00f8f7f
...@@ -3047,23 +3047,21 @@ String *Item_load_file::val_str(String *str) ...@@ -3047,23 +3047,21 @@ String *Item_load_file::val_str(String *str)
String* Item_func_export_set::val_str(String* str) String* Item_func_export_set::val_str(String* str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
ulonglong the_set = (ulonglong) args[0]->val_int(); String yes_buf, no_buf, sep_buf;
String yes_buf, *yes; const ulonglong the_set = (ulonglong) args[0]->val_int();
yes = args[1]->val_str(&yes_buf); const String *yes= args[1]->val_str(&yes_buf);
String no_buf, *no; const String *no= args[2]->val_str(&no_buf);
no = args[2]->val_str(&no_buf); const String *sep= NULL;
String *sep = NULL, sep_buf ;
uint num_set_values = 64; uint num_set_values = 64;
ulonglong mask = 0x1;
str->length(0); str->length(0);
str->set_charset(collation.collation); str->set_charset(collation.collation);
/* Check if some argument is a NULL value */ /* Check if some argument is a NULL value */
if (args[0]->null_value || args[1]->null_value || args[2]->null_value) if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
{ {
null_value=1; null_value= true;
return 0; return NULL;
} }
/* /*
Arg count can only be 3, 4 or 5 here. This is guaranteed from the Arg count can only be 3, 4 or 5 here. This is guaranteed from the
...@@ -3076,37 +3074,56 @@ String* Item_func_export_set::val_str(String* str) ...@@ -3076,37 +3074,56 @@ String* Item_func_export_set::val_str(String* str)
num_set_values=64; num_set_values=64;
if (args[4]->null_value) if (args[4]->null_value)
{ {
null_value=1; null_value= true;
return 0; return NULL;
} }
/* Fall through */ /* Fall through */
case 4: case 4:
if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL
{ {
null_value=1; null_value= true;
return 0; return NULL;
} }
break; break;
case 3: case 3:
{ {
/* errors is not checked - assume "," can always be converted */ /* errors is not checked - assume "," can always be converted */
uint errors; uint errors;
sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors); sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin,
collation.collation, &errors);
sep = &sep_buf; sep = &sep_buf;
} }
break; break;
default: default:
DBUG_ASSERT(0); // cannot happen DBUG_ASSERT(0); // cannot happen
} }
null_value=0; null_value= false;
const ulong max_allowed_packet= current_thd->variables.max_allowed_packet;
const uint num_separators= num_set_values > 0 ? num_set_values - 1 : 0;
const ulonglong max_total_length=
num_set_values * max(yes->length(), no->length()) +
num_separators * sep->length();
if (unlikely(max_total_length > max_allowed_packet))
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), max_allowed_packet);
null_value= true;
return NULL;
}
for (uint i = 0; i < num_set_values; i++, mask = (mask << 1)) uint ix;
ulonglong mask;
for (ix= 0, mask=0x1; ix < num_set_values; ++ix, mask = (mask << 1))
{ {
if (the_set & mask) if (the_set & mask)
str->append(*yes); str->append(*yes);
else else
str->append(*no); str->append(*no);
if (i != num_set_values - 1) if (ix != num_separators)
str->append(*sep); str->append(*sep);
} }
return str; return str;
......
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