summaryrefslogtreecommitdiff
path: root/sql/sql_partition.cc
diff options
context:
space:
mode:
authorGuilhem Bichot <guilhem.bichot@oracle.com>2013-07-24 14:33:52 +0200
committerGuilhem Bichot <guilhem.bichot@oracle.com>2013-07-24 14:33:52 +0200
commitb420ff498304102e157f9fd978e1b34e18d292ae (patch)
tree6bf839402e3537b1a9c834d93d616aecba467fbd /sql/sql_partition.cc
parent70cb66b96fd6bc6605c1b9d8ecff4ca78103973e (diff)
downloadmariadb-git-b420ff498304102e157f9fd978e1b34e18d292ae.tar.gz
Fix for Bug#16614004 CRASH AFTER READING FREED MEMORY AFTER DOING DDL IN STORED ROUTINE
Inside a loop in a stored procedure, we create a partitioned table. The CREATE statement is thus treated as a prepared statement: it is prepared once, and then executed by each iteration. Thus its Lex is reused many times. This Lex contains a part_info member, which describes how the partitions should be laid out, including the partitioning function. Each execution of the CREATE does this, in open_table_from_share (): tmp= mysql_unpack_partition(thd, share->partition_info_str, share->partition_info_str_len, outparam, is_create_table, share->default_part_db_type, &work_part_info_used); ... tmp= fix_partition_func(thd, outparam, is_create_table); The first line calls init_lex_with_single_table() which creates a TABLE_LIST, necessary for the "field fixing" which will be done by the second line; this is how it is created: if ((!(table_ident= new Table_ident(thd, table->s->db, table->s->table_name, TRUE))) || (!(table_list= select_lex->add_table_to_list(thd, table_ident, NULL, 0)))) return TRUE; it is allocated in the execution memory root. Then the partitioning function ("id", stored in Lex -> part_info) is fixed, which calls Item_ident:: fix_fields (), which resolves "id" to the table_list above, and stores in the item's cached_table a pointer to this table_list. The table is created, later it is dropped by another statement, then we execute again the prepared CREATE. This reuses the Lex, thus also its part_info, thus also the item representing the partitioning function (part_info is cloned but it's a shallow cloning); CREATE wants to fix the item again (which is normal, every execution fixes items again), fix_fields () sees that the cached_table pointer is set and picks up the pointed table_list. But this last object does not exist anymore (it was allocated in the execution memory root of the previous execution, so it has been freed), so we access invalid memory. The solution: when creating the table_list, mark that it cannot be cached.
Diffstat (limited to 'sql/sql_partition.cc')
-rw-r--r--sql/sql_partition.cc1
1 files changed, 1 insertions, 0 deletions
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index cd4652b19be..7e8e76f5e13 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1007,6 +1007,7 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
table->map= 1; //To ensure correct calculation of const item
table->get_fields_in_item_tree= TRUE;
table_list->table= table;
+ table_list->cacheable_table= false;
return FALSE;
}