1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-29624 MDEV-29655 Fix ASAN errors on pushdown of derived table

Deallocation of TABLE_LIST::dt_handler and TABLE_LIST::pushdown_derived
was performed in multiple places if code. This not only made the code
more difficult to maintain but also led to memory leaks and
ASAN heap-use-after-free errors.
This commit puts deallocation of TABLE_LIST::dt_handler and
TABLE_LIST::pushdown_derived to the single point - JOIN::cleanup()
This commit is contained in:
Oleg Smirnov
2022-10-19 13:26:19 +04:00
parent ce443c8554
commit 0d927a57d2
6 changed files with 132 additions and 19 deletions

View File

@ -68,6 +68,7 @@
#include "select_handler.h"
#include "my_json_writer.h"
#include "opt_trace.h"
#include "derived_handler.h"
/*
A key part number that means we're using a fulltext scan.
@ -14086,6 +14087,7 @@ void JOIN::cleanup(bool full)
}
}
}
free_pushdown_handlers(*join_list);
}
/* Restore ref array to original state */
if (current_ref_ptrs != items0)
@ -14096,6 +14098,32 @@ void JOIN::cleanup(bool full)
DBUG_VOID_RETURN;
}
/**
Clean up all derived pushdown handlers in this join.
@detail
Note that dt_handler is picked at the prepare stage (as opposed
to optimization stage where one could expect this).
Because of that, we have to do cleanups in this function that is called
from JOIN::cleanup() and not in JOIN_TAB::cleanup.
*/
void JOIN::free_pushdown_handlers(List<TABLE_LIST>& join_list)
{
List_iterator<TABLE_LIST> li(join_list);
TABLE_LIST *table_ref;
while ((table_ref= li++))
{
if (table_ref->nested_join)
free_pushdown_handlers(table_ref->nested_join->join_list);
if (table_ref->pushdown_derived)
{
delete table_ref->pushdown_derived;
table_ref->pushdown_derived= NULL;
}
delete table_ref->dt_handler;
table_ref->dt_handler= NULL;
}
}
/**
Remove the following expressions from ORDER BY and GROUP BY:
@ -27400,12 +27428,6 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
result, unit, first);
}
if (unit->derived && unit->derived->pushdown_derived)
{
delete unit->derived->pushdown_derived;
unit->derived->pushdown_derived= NULL;
}
DBUG_RETURN(res || thd->is_error());
}