mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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
This commit is contained in:
@ -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;
|
|||||||
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()
|
|||||||
{
|
{
|
||||||
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()
|
|||||||
/*
|
/*
|
||||||
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,
|
|||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user