1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00

MDEV-32369: Memory leak when executing PS for query with IN subquery

The memory allocated for an instance of the class Item_direct_ref_to_item
was leaked on second execution of a query run as a prepared statement and
involving conversion of strings with different character sets.

The reason of leaking the memory was caused by the fact that a statement
arena could be already set by the moment the method
Type_std_attributes::agg_item_set_converter() is called.
This commit is contained in:
Dmitry Shulga
2023-10-18 11:15:16 +07:00
parent 6f83537876
commit ac15141448
3 changed files with 51 additions and 5 deletions

View File

@@ -0,0 +1,16 @@
#
# MDEV-32369: Memory leak when executing PS for query with IN subquery
#
CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM;
CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM;
INSERT INTO t1 VALUES ('b');
INSERT INTO t2 VALUES ('b');
PREPARE stmt FROM "SELECT t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)";
EXECUTE stmt;
a
b
EXECUTE stmt;
a
b
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;

View File

@@ -0,0 +1,27 @@
# This file contains test cases that use the memory leaks detection feature
# provided by the cmake build option -DWITH_PROTECT_STATEMENT_MEMROOT
--source include/not_embedded.inc
# The cmake option -DWITH_PROTECT_STATEMENT_MEMROOT is used only
# for debug build
--source include/have_debug.inc
--echo #
--echo # MDEV-32369: Memory leak when executing PS for query with IN subquery
--echo #
CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM;
CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM;
INSERT INTO t1 VALUES ('b');
INSERT INTO t2 VALUES ('b');
PREPARE stmt FROM "SELECT t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;

View File

@@ -2584,19 +2584,22 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
if (conv->fix_fields_if_needed(thd, arg))
return TRUE;
Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
if (arena)
if (!thd->stmt_arena->is_conventional())
{
Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
Item_direct_ref_to_item *ref=
new (thd->mem_root) Item_direct_ref_to_item(thd, *arg);
if ((ref == NULL) || ref->fix_fields(thd, (Item **)&ref))
{
thd->restore_active_arena(arena, &backup);
if (arena)
thd->restore_active_arena(arena, &backup);
return TRUE;
}
*arg= ref;
thd->restore_active_arena(arena, &backup);
if (arena)
thd->restore_active_arena(arena, &backup);
ref->change_item(thd, conv);
}
else