Commit b0a8fde8 authored by unknown's avatar unknown

Fixed stack overrun with some INSERT ... SELECT ... GROUP BY queries (Bug #3265)

Ensure that raid_chunks is not set to higher than 255 as this could cause problems with DROP DATABASE. (Bug #3182)


mysql-test/r/raid.result:
  Test of raid_chunks > 255
mysql-test/t/raid.test:
  Test of raid_chunks > 255
sql/item.cc:
  Fixed wrong usage of str_value in Item::save_in_field
  This could caused a stack overrun with some very special INSERT ... SELECT ... GROUP BY queries where the GROUP BY value was an expression that generated a NULL value. (Bug #3265)
  The Item_copy_string::save_in_field() function is from 4.1 and helps optimized this case a bit
sql/item.h:
  Fixed wrong usage of str_value in Item_copy_string::save_in_field
sql/sql_insert.cc:
  More debug information
sql/table.cc:
  Ensure that raid_chunks is not set to higher than 255 as this could cause problems with DROP DATABASE.
  Another problem with values > 255 is that in the .frm file we store the chunks value in one byte.
  (Bug #3182)
parent b825d9b0
...@@ -2,6 +2,14 @@ create database test_raid; ...@@ -2,6 +2,14 @@ create database test_raid;
create table test_raid.r1 (i int) raid_type=1; create table test_raid.r1 (i int) raid_type=1;
create table test_raid.r2 (i int) raid_type=1 raid_chunks=32; create table test_raid.r2 (i int) raid_type=1 raid_chunks=32;
drop database test_raid; drop database test_raid;
create database test_raid;
create table test_raid.r2 (i int) raid_type=1 raid_chunks=257;
show create table test_raid.r2;
Table Create Table
r2 CREATE TABLE `r2` (
`i` int(11) default NULL
) TYPE=MyISAM RAID_TYPE=striped RAID_CHUNKS=255 RAID_CHUNKSIZE=256
drop database test_raid;
DROP TABLE IF EXISTS t1,t2; DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
id int unsigned not null auto_increment primary key, id int unsigned not null auto_increment primary key,
......
...@@ -11,6 +11,15 @@ create database test_raid; ...@@ -11,6 +11,15 @@ create database test_raid;
create table test_raid.r1 (i int) raid_type=1; create table test_raid.r1 (i int) raid_type=1;
create table test_raid.r2 (i int) raid_type=1 raid_chunks=32; create table test_raid.r2 (i int) raid_type=1 raid_chunks=32;
drop database test_raid; drop database test_raid;
#
# Bug #3182: Test using more than 257 raid chunks
#
create database test_raid;
create table test_raid.r2 (i int) raid_type=1 raid_chunks=257;
show create table test_raid.r2;
drop database test_raid;
DROP TABLE IF EXISTS t1,t2; DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
id int unsigned not null auto_increment primary key, id int unsigned not null auto_increment primary key,
......
...@@ -322,6 +322,15 @@ String *Item_copy_string::val_str(String *str) ...@@ -322,6 +322,15 @@ String *Item_copy_string::val_str(String *str)
return &str_value; return &str_value;
} }
bool Item_copy_string::save_in_field(Field *field, bool no_conversions)
{
if (null_value)
return set_field_to_null(field);
field->set_notnull();
field->store(str_value.ptr(), str_value.length());
return 0;
}
/* /*
** Functions to convert item to field (for send_fields) ** Functions to convert item to field (for send_fields)
*/ */
...@@ -520,7 +529,10 @@ bool Item::save_in_field(Field *field, bool no_conversions) ...@@ -520,7 +529,10 @@ bool Item::save_in_field(Field *field, bool no_conversions)
str_value.set_quick(buff,sizeof(buff)); str_value.set_quick(buff,sizeof(buff));
result=val_str(&str_value); result=val_str(&str_value);
if (null_value) if (null_value)
{
str_value.set_quick(0, 0);
return set_field_to_null_with_conversions(field, no_conversions); return set_field_to_null_with_conversions(field, no_conversions);
}
field->set_notnull(); field->set_notnull();
field->store(result->ptr(),result->length()); field->store(result->ptr(),result->length());
str_value.set_quick(0, 0); str_value.set_quick(0, 0);
......
...@@ -499,6 +499,7 @@ class Item_copy_string :public Item ...@@ -499,6 +499,7 @@ class Item_copy_string :public Item
String *val_str(String*); String *val_str(String*);
void make_field(Send_field *field) { item->make_field(field); } void make_field(Send_field *field) { item->make_field(field); }
void copy(); void copy();
bool save_in_field(Field *field, bool no_conversions);
table_map used_tables() const { return (table_map) 1L; } table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; } bool const_item() const { return 0; }
bool is_null() { return null_value; } bool is_null() { return null_value; }
......
...@@ -391,6 +391,7 @@ int write_record(TABLE *table,COPY_INFO *info) ...@@ -391,6 +391,7 @@ int write_record(TABLE *table,COPY_INFO *info)
{ {
int error; int error;
char *key=0; char *key=0;
DBUG_ENTER("write_record");
info->records++; info->records++;
if (info->handle_duplicates == DUP_REPLACE) if (info->handle_duplicates == DUP_REPLACE)
...@@ -474,14 +475,14 @@ int write_record(TABLE *table,COPY_INFO *info) ...@@ -474,14 +475,14 @@ int write_record(TABLE *table,COPY_INFO *info)
info->copied++; info->copied++;
if (key) if (key)
my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH); my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH);
return 0; DBUG_RETURN(0);
err: err:
if (key) if (key)
my_afree(key); my_afree(key);
info->last_errno= error; info->last_errno= error;
table->file->print_error(error,MYF(0)); table->file->print_error(error,MYF(0));
return 1; DBUG_RETURN(1);
} }
...@@ -1342,24 +1343,25 @@ select_insert::~select_insert() ...@@ -1342,24 +1343,25 @@ select_insert::~select_insert()
bool select_insert::send_data(List<Item> &values) bool select_insert::send_data(List<Item> &values)
{ {
DBUG_ENTER("select_insert::send_data");
if (thd->offset_limit) if (thd->offset_limit)
{ // using limit offset,count { // using limit offset,count
thd->offset_limit--; thd->offset_limit--;
return 0; DBUG_RETURN(0);
} }
if (fields->elements) if (fields->elements)
fill_record(*fields, values, 1); fill_record(*fields, values, 1);
else else
fill_record(table->field, values, 1); fill_record(table->field, values, 1);
if (write_record(table,&info)) if (write_record(table,&info))
return 1; DBUG_RETURN(1);
if (table->next_number_field) // Clear for next record if (table->next_number_field) // Clear for next record
{ {
table->next_number_field->reset(); table->next_number_field->reset();
if (! last_insert_id && thd->insert_id_used) if (! last_insert_id && thd->insert_id_used)
last_insert_id=thd->insert_id(); last_insert_id=thd->insert_id();
} }
return 0; DBUG_RETURN(0);
} }
......
...@@ -1040,6 +1040,11 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, ...@@ -1040,6 +1040,11 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
if (create_info->min_rows > ~(ulong) 0) if (create_info->min_rows > ~(ulong) 0)
create_info->min_rows= ~(ulong) 0; create_info->min_rows= ~(ulong) 0;
#endif #endif
/*
Ensure that raid_chunks can't be larger than 255, as this would cause
problems with drop database
*/
set_if_smaller(create_info->raid_chunks, 255);
if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{ {
......
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