Commit 5064750f authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-32466: Potential memory leak on executing of create view statement

This patch is actually follow-up for the task
  MDEV-23902: MariaDB crash on calling function
to use correct query arena for a statement. In case invocation of
a function is in progress use its call arena, else use current
query arena that can be either a statement or a regular query arena.
parent bdfd93d3
...@@ -57,4 +57,26 @@ EXECUTE stmt; ...@@ -57,4 +57,26 @@ EXECUTE stmt;
exp exp
0 0
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
#
# MDEV-32466: Potential memory leak on execuing of create view statement
#
CREATE FUNCTION f1 () RETURNS VARCHAR(1)
BEGIN
DECLARE rec1 ROW TYPE OF v1;
SELECT z INTO rec1 FROM v1;
RETURN 1;
END|
CREATE FUNCTION f2 () RETURNS VARCHAR(1) RETURN '!';
CREATE VIEW v1 AS SELECT f2() z;
PREPARE stmt FROM "SELECT f1()";
EXECUTE stmt;
f1()
1
EXECUTE stmt;
f1()
1
DEALLOCATE PREPARE stmt;
DROP FUNCTION f1;
DROP VIEW v1;
DROP FUNCTION f2;
# End of 10.4 tests # End of 10.4 tests
...@@ -69,4 +69,32 @@ EXECUTE stmt; ...@@ -69,4 +69,32 @@ EXECUTE stmt;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
--echo #
--echo # MDEV-32466: Potential memory leak on execuing of create view statement
--echo #
--delimiter |
CREATE FUNCTION f1 () RETURNS VARCHAR(1)
BEGIN
DECLARE rec1 ROW TYPE OF v1;
SELECT z INTO rec1 FROM v1;
RETURN 1;
END|
--delimiter ;
CREATE FUNCTION f2 () RETURNS VARCHAR(1) RETURN '!';
CREATE VIEW v1 AS SELECT f2() z;
PREPARE stmt FROM "SELECT f1()";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Clean up
DROP FUNCTION f1;
DROP VIEW v1;
DROP FUNCTION f2;
--echo # End of 10.4 tests --echo # End of 10.4 tests
...@@ -2720,7 +2720,8 @@ void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx, ...@@ -2720,7 +2720,8 @@ void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *belong_to_view) TABLE_LIST *belong_to_view)
{ {
for (Sroutine_hash_entry *rt= src->first; rt; rt= rt->next) for (Sroutine_hash_entry *rt= src->first; rt; rt= rt->next)
(void)sp_add_used_routine(prelocking_ctx, thd->stmt_arena,
(void)sp_add_used_routine(prelocking_ctx, thd->active_stmt_arena_to_use(),
&rt->mdl_request.key, rt->m_handler, &rt->mdl_request.key, rt->m_handler,
belong_to_view); belong_to_view);
} }
......
...@@ -7740,7 +7740,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, ...@@ -7740,7 +7740,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
while ((item= it++)) while ((item= it++))
{ {
if (make_pre_fix) if (make_pre_fix)
pre_fix->push_back(item, thd->stmt_arena->mem_root); pre_fix->push_back(item, thd->active_stmt_arena_to_use()->mem_root);
if (item->fix_fields_if_needed_for_scalar(thd, it.ref())) if (item->fix_fields_if_needed_for_scalar(thd, it.ref()))
{ {
......
...@@ -2790,6 +2790,17 @@ class THD: public THD_count, /* this must be first */ ...@@ -2790,6 +2790,17 @@ class THD: public THD_count, /* this must be first */
*/ */
Query_arena *stmt_arena; Query_arena *stmt_arena;
/**
Get either call or statement arena. In case some function is called from
within a query the call arena has to be used for a memory allocation,
else use the statement arena.
*/
Query_arena *active_stmt_arena_to_use()
{
return (state == Query_arena::STMT_SP_QUERY_ARGUMENTS) ? this :
stmt_arena;
}
void *bulk_param; void *bulk_param;
/* /*
......
...@@ -3115,8 +3115,9 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) ...@@ -3115,8 +3115,9 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
uint n_elems= get_cardinality_of_ref_ptrs_slice(order_group_num) * 5; uint n_elems= get_cardinality_of_ref_ptrs_slice(order_group_num) * 5;
if (!ref_pointer_array.is_null()) if (!ref_pointer_array.is_null())
return false; return false;
Item **array= static_cast<Item**>(thd->stmt_arena->alloc(sizeof(Item*) *
n_elems)); Item **array= static_cast<Item**>(
thd->active_stmt_arena_to_use()->alloc(sizeof(Item*) * n_elems));
if (likely(array != NULL)) if (likely(array != NULL))
ref_pointer_array= Ref_ptr_array(array, n_elems); ref_pointer_array= Ref_ptr_array(array, n_elems);
return array == NULL; return array == NULL;
......
...@@ -1655,7 +1655,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, ...@@ -1655,7 +1655,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
objects of the view. objects of the view.
*/ */
if (!(table->view_sctx= (Security_context *) if (!(table->view_sctx= (Security_context *)
thd->stmt_arena->calloc(sizeof(Security_context)))) thd->active_stmt_arena_to_use()->calloc(sizeof(Security_context))))
goto err; goto err;
security_ctx= table->view_sctx; security_ctx= table->view_sctx;
} }
......
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