1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-31432 tmp_table field accessed after free

Before this patch, the code in Item_field::print() used
this convention (described in sql_explain.h:ExplainDataStructureLifetime):

- By default, the table that Item_field refers to is accessible.
- ANALYZE and SHOW {EXPLAIN|ANALYZE} may print Items after some
  temporary tables have been dropped. They use
  QT_DONT_ACCESS_TMP_TABLES flag. When it is ON, Item_field::print
  will not access the table it refers to, if it is a temp.table

The bug was that EXPLAIN statement also may compute subqueries (depending
on subquery context and @@expensive_subquery_limit setting). After the
computation, the subquery calls JOIN::cleanup(true) which drops some of
its temporary tables. Calling Item_field::print() that refer to such table
will cause an access to free'd memory.

In this patch, we take into account that query optimization can compute
a subquery and discard its temporary tables. Item_field::print() now
assumes that any temporary table might have already been dropped.
This means QT_DONT_ACCESS_TMP_TABLES flag is not needed - we imply it is
always present.

But we also make one exception: derived tables are not freed in
JOIN::cleanup() call. They are freed later in close_thread_tables(),
at the same time when regular tables are closed.
Because of that, Item_field::print may assume that temp.tables
representing derived tables are available.

Initial patch by: Rex Jonston
Reviewed by: Monty <monty@mariadb.org>
This commit is contained in:
Sergei Petrunia
2023-08-14 11:09:51 +03:00
parent 9cd2989589
commit 8aaacb5509
15 changed files with 199 additions and 157 deletions

View File

@@ -20014,7 +20014,7 @@ bool Create_tmp_table::add_fields(THD *thd,
if (!(tmp_item= new (thd->mem_root)
Item_field(thd, new_field)))
goto err;
((Item_field*) tmp_item)->set_refers_to_temp_table(true);
((Item_field*) tmp_item)->set_refers_to_temp_table();
arg= sum_item->set_arg(i, thd, tmp_item);
thd->mem_root= &table->mem_root;
@@ -27290,7 +27290,7 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
Item_field *new_field= new (thd->mem_root) Item_field(thd, field);
if (!suv || !new_field)
DBUG_RETURN(true); // Fatal error
new_field->set_refers_to_temp_table(true);
new_field->set_refers_to_temp_table();
List<Item> list;
list.push_back(new_field, thd->mem_root);
suv->set_arguments(thd, list);
@@ -27309,7 +27309,7 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
{
item_field= (Item*) new (thd->mem_root) Item_field(thd, field);
if (item_field)
((Item_field*) item_field)->set_refers_to_temp_table(true);
((Item_field*) item_field)->set_refers_to_temp_table();
}
if (!item_field)
DBUG_RETURN(true); // Fatal error