Commit 2a1ae3a5 authored by unknown's avatar unknown
Browse files

A fix and a test case for Bug#14410 "Crash in Enum or Set type in

CREATE TABLE and PS/SP": make sure that 'typelib' object for
ENUM values and 'Item_string' object for DEFAULT clause are 
created in the statement memory root.


mysql-test/r/ps.result:
  Test results has been fixed (Bug#14410)
mysql-test/t/ps.test:
  A test case for Bug#14410 "Crash in Enum or Set type in CREATE 
  TABLE and PS/SP"
sql/mysql_priv.h:
  typelib() function declaration has been changed.
sql/sql_table.cc:
  Supply the statement memory root to use in typelib() and
  safe_charset_converter() functions to ensure that objects 
  created during the first execution of CREATE TABLE statement
  are allocated in persistent memory of the statement.
sql/table.cc:
  Change typelib() function to require MEM_ROOT.
parent 6fb8a4e9
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -699,3 +699,22 @@ execute stmt;
@@tx_isolation
REPEATABLE-READ
deallocate prepare stmt;
prepare stmt from "create temporary table t1 (letter enum('','a','b','c')
not null)";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
set names latin1;
prepare stmt from "create table t1 (a enum('test') default 'test')
 character set utf8";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
set names default;
deallocate prepare stmt;
+29 −0
Original line number Diff line number Diff line
@@ -718,4 +718,33 @@ set @@tx_isolation=default;
execute stmt;
deallocate prepare stmt;

#
# Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP"
#
# Part I. Make sure the typelib for ENUM is created in the statement memory
# root.
prepare stmt from "create temporary table t1 (letter enum('','a','b','c')
not null)";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
# Part II. Make sure that when the default value is converted to UTF-8,
# the new item is # created in the statement memory root.
set names latin1;
prepare stmt from "create table t1 (a enum('test') default 'test')
 character set utf8";
execute stmt;
drop table t1;
execute stmt;
drop table t1;
execute stmt;
drop table t1;
# Cleanup
set names default;
deallocate prepare stmt;

# End of 4.1 tests
+1 −1
Original line number Diff line number Diff line
@@ -1119,7 +1119,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week);
uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
void find_date(char *pos,uint *vek,uint flag);
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
TYPELIB *typelib(List<String> &strings);
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings);
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
		     const char *newname);
+25 −4
Original line number Diff line number Diff line
@@ -524,7 +524,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
      */
      if (!interval)
      {
        interval= sql_field->interval= typelib(sql_field->interval_list);
        /*
          Create the typelib in prepared statement memory if we're
          executing one.
        */
        MEM_ROOT *stmt_root= thd->current_arena->mem_root;

        interval= sql_field->interval= typelib(stmt_root,
                                               sql_field->interval_list);
        List_iterator<String> it(sql_field->interval_list);
        String conv, *tmp;
        for (uint i= 0; (tmp= it++); i++)
@@ -534,7 +541,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
          {
            uint cnv_errs;
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
            char *buf= (char*) sql_alloc(conv.length()+1);
            char *buf= (char*) alloc_root(stmt_root, conv.length()+1);
            memcpy(buf, conv.ptr(), conv.length());
            buf[conv.length()]= '\0';
            interval->type_names[i]= buf;
@@ -556,8 +563,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
      */
      if (sql_field->def && cs != sql_field->def->collation.collation)
      {
        if (!(sql_field->def= 
              sql_field->def->safe_charset_converter(cs)))
        Item_arena backup_arena;
        bool need_to_change_arena=
          !thd->current_arena->is_conventional_execution();
        if (need_to_change_arena)
        {
          /* Asser that we don't do that at every PS execute */
          DBUG_ASSERT(thd->current_arena->is_first_stmt_execute());
          thd->set_n_backup_item_arena(thd->current_arena, &backup_arena);
        }

        sql_field->def= sql_field->def->safe_charset_converter(cs);

        if (need_to_change_arena)
          thd->restore_backup_item_arena(thd->current_arena, &backup_arena);

        if (! sql_field->def)
        {
          /* Could not convert */
          my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+3 −3
Original line number Diff line number Diff line
@@ -1099,15 +1099,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
} /* fix_type_pointers */


TYPELIB *typelib(List<String> &strings)
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
{
  TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB));
  TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
  if (!result)
    return 0;
  result->count=strings.elements;
  result->name="";
  uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
  if (!(result->type_names= (const char**) sql_alloc(nbytes)))
  if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
    return 0;
  result->type_lengths= (uint*) (result->type_names + result->count + 1);
  List_iterator<String> it(strings);