revision-id: 5651e72b8dd20e29a4963723773ec6bcfac457ba (mariadb-10.3.6-102-g5651e72) parent(s): 73a10cbcc5178ae5378abb821428d35d3276b4da committer: Alexey Botchkov timestamp: 2018-05-03 12:42:56 +0400 message: MDEV-15465 Server crash or ASAN heap-use-after-free in Item_func_match::cleanup upon using FT search with partitioning. The Item_func_match::cleanup() uses table's internals so it's not safe to call it after the close_thread_tables(). Let's call it in st_select_lex::cleanup(). --- mysql-test/main/partition_sync.result | 25 ++++++++++++++++++++++++ mysql-test/main/partition_sync.test | 36 +++++++++++++++++++++++++++++++++++ sql/sql_base.cc | 13 +++++++++++++ sql/sql_base.h | 1 + sql/sql_union.cc | 1 + 5 files changed, 76 insertions(+) diff --git a/mysql-test/main/partition_sync.result b/mysql-test/main/partition_sync.result index 18cc506..badcb10 100644 --- a/mysql-test/main/partition_sync.result +++ b/mysql-test/main/partition_sync.result @@ -61,3 +61,28 @@ connection default; disconnect con2; disconnect con3; DROP TABLE tbl_with_partitions; +# +# MDEV-15465 Server crash or ASAN heap-use-after-free in Item_func_match::cleanup +# upon using FT search with partitioning. +# +connect con1,localhost,root,,test; +CREATE OR REPLACE TABLE t1 (c CHAR(8)) ENGINE=MyISAM PARTITION BY KEY(c); +connection default; +set debug_sync= 'execute_command_after_close_tables SIGNAL opened WAIT_FOR go'; +DELETE FROM t1 WHERE MATCH(c) AGAINST ('foo' IN BOOLEAN MODE); +connection con1; +set debug_sync= 'now WAIT_FOR opened'; +FLUSH TABLES; +set debug_sync= 'now SIGNAL go'; +connection default; +set debug_sync= 'execute_command_after_close_tables SIGNAL opened WAIT_FOR go'; +SELECT * FROM t1 WHERE MATCH(c) AGAINST ('foo' IN BOOLEAN MODE); +connection con1; +set debug_sync= 'now WAIT_FOR opened'; +FLUSH TABLES; +set debug_sync= 'now SIGNAL go'; +disconnect con1; +connection default; +c +DROP TABLE t1; +set debug_sync= 'RESET'; diff --git a/mysql-test/main/partition_sync.test b/mysql-test/main/partition_sync.test index fd704f3..22ca7df 100644 --- a/mysql-test/main/partition_sync.test +++ b/mysql-test/main/partition_sync.test @@ -77,6 +77,42 @@ disconnect con2; disconnect con3; DROP TABLE tbl_with_partitions; +--echo # +--echo # MDEV-15465 Server crash or ASAN heap-use-after-free in Item_func_match::cleanup +--echo # upon using FT search with partitioning. +--echo # + +--connect (con1,localhost,root,,test) +CREATE OR REPLACE TABLE t1 (c CHAR(8)) ENGINE=MyISAM PARTITION BY KEY(c); + +--connection default +set debug_sync= 'execute_command_after_close_tables SIGNAL opened WAIT_FOR go'; +--send +DELETE FROM t1 WHERE MATCH(c) AGAINST ('foo' IN BOOLEAN MODE); + +--connection con1 +set debug_sync= 'now WAIT_FOR opened'; +FLUSH TABLES; +set debug_sync= 'now SIGNAL go'; + +--connection default +--reap +set debug_sync= 'execute_command_after_close_tables SIGNAL opened WAIT_FOR go'; +--send +SELECT * FROM t1 WHERE MATCH(c) AGAINST ('foo' IN BOOLEAN MODE); + +--connection con1 +set debug_sync= 'now WAIT_FOR opened'; +FLUSH TABLES; +set debug_sync= 'now SIGNAL go'; + +# Cleanup +--disconnect con1 +--connection default +--reap +DROP TABLE t1; +set debug_sync= 'RESET'; + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0081365..673473e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8639,6 +8639,19 @@ int setup_ftfuncs(SELECT_LEX *select_lex) } +void cleanup_ftfuncs(SELECT_LEX *select_lex) +{ + List_iterator<Item_func_match> li(*(select_lex->ftfunc_list)), + lj(*(select_lex->ftfunc_list)); + Item_func_match *ftf; + + while ((ftf=li++)) + { + ftf->cleanup(); + } +} + + int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) { if (select_lex->ftfunc_list->elements) diff --git a/sql/sql_base.h b/sql/sql_base.h index 8f6d406..645a4a8 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -216,6 +216,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves, COND **conds); void wrap_ident(THD *thd, Item **conds); int setup_ftfuncs(SELECT_LEX* select); +void cleanup_ftfuncs(SELECT_LEX *select_lex); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); bool lock_table_names(THD *thd, const DDL_options_st &options, TABLE_LIST *table_list, diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 432ad85..0bd654c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1909,6 +1909,7 @@ bool st_select_lex::cleanup() cleanup_order(order_list.first); cleanup_order(group_list.first); + cleanup_ftfuncs(this); if (join) {