From ad7da60deda2cf97e60118a58f50f648abde6448 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sun, 26 Mar 2017 22:59:33 -0700 Subject: [PATCH] Fixed bug mdev-12368. Mutually recursive CTE could cause a crash of the server in the case when they were not Standard compliant. The crash happened in mysql_derived_prepare(), because the destructor the derived_result object created for a CTE that was mutually recursive with some others was called twice. Yet this destructor should not be called for resursive references. --- mysql-test/r/cte_recursive.result | 35 +++++++++++++++++++++++++++ mysql-test/t/cte_recursive.test | 39 +++++++++++++++++++++++++++++++ sql/sql_derived.cc | 9 ++++--- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index 6d59d6749dfe9..bfca93cf6d6cb 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -2453,3 +2453,38 @@ id name dob father mother 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL drop table folks; +# +# mdev-12368: crash with mutually recursive CTE +# that arenot Standard compliant +# +create table value_nodes (v char(4)); +create table module_nodes(m char(4)); +create table module_arguments(m char(4), v char(4)); +create table module_results(m char(4), v char(4)); +with recursive +reached_values as +( +select v from value_nodes where v in ('v3','v7','v9') +union +select module_results.v from module_results, applied_modules +where module_results.m = applied_modules.m +), +applied_modules as +( +select module_nodes.m +from +module_nodes +left join +( +module_arguments +left join +reached_values +on module_arguments.v = reached_values.v +) +on reached_values.v is null and +module_nodes.m = module_arguments.m +where module_arguments.m is null +) +select * from reached_values; +ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'applied_modules' +drop table value_nodes, module_nodes, module_arguments, module_results; diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index 37f66bbc4db9e..592cdd4f8d129 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -1559,3 +1559,42 @@ as select * from ancestors; drop table folks; + +--echo # +--echo # mdev-12368: crash with mutually recursive CTE +--echo # that arenot Standard compliant +--echo # + +create table value_nodes (v char(4)); +create table module_nodes(m char(4)); +create table module_arguments(m char(4), v char(4)); +create table module_results(m char(4), v char(4)); + +--ERROR ER_NOT_STANDARD_COMPLIANT_RECURSIVE +with recursive +reached_values as +( + select v from value_nodes where v in ('v3','v7','v9') + union + select module_results.v from module_results, applied_modules + where module_results.m = applied_modules.m +), +applied_modules as +( + select module_nodes.m + from + module_nodes + left join + ( + module_arguments + left join + reached_values + on module_arguments.v = reached_values.v + ) + on reached_values.v is null and + module_nodes.m = module_arguments.m + where module_arguments.m is null +) +select * from reached_values; + +drop table value_nodes, module_nodes, module_arguments, module_results; \ No newline at end of file diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 76cb27d7d62a7..faf6dd790a631 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -789,9 +789,12 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) */ if (res) { - if (derived->table && !derived->is_with_table_recursive_reference()) - free_tmp_table(thd, derived->table); - delete derived->derived_result; + if (!derived->is_with_table_recursive_reference()) + { + if (derived->table) + free_tmp_table(thd, derived->table); + delete derived->derived_result; + } } else {