Commit 1cc67e09 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-16153 Server crashes in Apc_target::disable, ASAN heap-use-after-free in...

MDEV-16153 Server crashes in Apc_target::disable, ASAN heap-use-after-free in Explain_query::~Explain_query upon/after EXECUTE IMMEDIATE

Explain_query must be created in the execution arena.
But JOIN::optimize_inner temporarily switches to the statement arena
under `if (sel->first_cond_optimization)`. This might cause
Explain_query to be allocated in the statement arena. Usually it is
harmless (although technically incorrect and a waste of memory), but
in case of EXECUTE IMMEDIATE, Prepared_statement object and its
statement arena are destroyed before log_slow_statement() call,
which uses Explain_query.

Fix:
1. Create Explain_query before switching arenas.
2. Before filling earlier-created Explain_query with data, set
thd->mem_root from the Explain_query::mem_root
parent 207e5ba3
...@@ -54,3 +54,7 @@ SELECT 1; ...@@ -54,3 +54,7 @@ SELECT 1;
1 1
SET log_slow_rate_limit=@save1; SET log_slow_rate_limit=@save1;
SET long_query_time=@save2; SET long_query_time=@save2;
create table t1 (a int);
execute immediate "select * from t1 join t1 t2 on (t1.a>5) where exists (select 1)";
a a
drop table t1;
...@@ -61,3 +61,9 @@ SELECT 1; ...@@ -61,3 +61,9 @@ SELECT 1;
SET log_slow_rate_limit=@save1; SET log_slow_rate_limit=@save1;
SET long_query_time=@save2; SET long_query_time=@save2;
#
# MDEV-16153 Server crashes in Apc_target::disable, ASAN heap-use-after-free in Explain_query::~Explain_query upon/after EXECUTE IMMEDIATE
#
create table t1 (a int);
execute immediate "select * from t1 join t1 t2 on (t1.a>5) where exists (select 1)";
drop table t1;
...@@ -1117,10 +1117,21 @@ int JOIN::optimize() ...@@ -1117,10 +1117,21 @@ int JOIN::optimize()
{ {
create_explain_query_if_not_exists(thd->lex, thd->mem_root); create_explain_query_if_not_exists(thd->lex, thd->mem_root);
have_query_plan= QEP_AVAILABLE; have_query_plan= QEP_AVAILABLE;
/*
explain data must be created on the Explain_query::mem_root. Because it's
just a memroot, not an arena, explain data must not contain any Items
*/
MEM_ROOT *old_mem_root= thd->mem_root;
Item *old_free_list __attribute__((unused))= thd->free_list;
thd->mem_root= thd->lex->explain->mem_root;
save_explain_data(thd->lex->explain, false /* can overwrite */, save_explain_data(thd->lex->explain, false /* can overwrite */,
need_tmp, need_tmp,
!skip_sort_order && !no_order && (order || group_list), !skip_sort_order && !no_order && (order || group_list),
select_distinct); select_distinct);
thd->mem_root= old_mem_root;
DBUG_ASSERT(thd->free_list == old_free_list); // no Items were created
uint select_nr= select_lex->select_number; uint select_nr= select_lex->select_number;
JOIN_TAB *curr_tab= join_tab + exec_join_tab_cnt(); JOIN_TAB *curr_tab= join_tab + exec_join_tab_cnt();
for (uint i= 0; i < aggr_tables; i++, curr_tab++) for (uint i= 0; i < aggr_tables; i++, curr_tab++)
...@@ -1294,7 +1305,11 @@ JOIN::optimize_inner() ...@@ -1294,7 +1305,11 @@ JOIN::optimize_inner()
/* /*
The following code will allocate the new items in a permanent The following code will allocate the new items in a permanent
MEMROOT for prepared statements and stored procedures. MEMROOT for prepared statements and stored procedures.
But first we need to ensure that thd->lex->explain is allocated
in the execution arena
*/ */
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
Query_arena *arena, backup; Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup); arena= thd->activate_stmt_arena_if_needed(&backup);
...@@ -24330,7 +24345,7 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, ...@@ -24330,7 +24345,7 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
if (filesort) if (filesort)
{ {
eta->pre_join_sort= new Explain_aggr_filesort(thd->mem_root, eta->pre_join_sort= new (thd->mem_root) Explain_aggr_filesort(thd->mem_root,
thd->lex->analyze_stmt, thd->lex->analyze_stmt,
filesort); filesort);
} }
......
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