diff options
author | Igor Babaev <igor@askmonty.org> | 2022-09-22 21:40:33 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2022-09-28 22:33:05 -0700 |
commit | 28ae361857686d49fce1933958b15f90db2047d1 (patch) | |
tree | efb026b19f389455ca3788357c99ec5c9883d752 /sql/sql_cte.h | |
parent | 9de9f105b5cb88249acc39af73d32af337d6fd5f (diff) | |
download | mariadb-git-28ae361857686d49fce1933958b15f90db2047d1.tar.gz |
MDEV-29361 Infinite recursive calls when detecting CTE dependencies
This patch resolves the problem of improper name resolution of table
references to embedded CTEs for some queries. This improper binding could
lead to
- infinite sequence of calls of recursive functions
- crashes due to resolution of null pointers
- wrong result sets returned by queries
- bogus error messages
If the definition of a CTE contains with clauses then such CTE is called
embedding CTE while CTEs from the with clauses are called embedded CTEs.
If a table reference used in the definition of an embedded CTE cannot be
resolved within the unit that contains this reference it still may be
resolved against a CTE definition from the with clause with one of the
embedding CTEs.
A table reference can be resolved against a CTE definition if it used in
the the scope of this definition and it refers to the name of the CTE.
Table reference t is in the scope of the CTE definition of CTE cte if
- the definition of cte is an element of a with clause declared as
RECURSIVE and the reference t belongs either to the unit to which
this with clause is attached or to one of the elements of this clause
- the definition of cte is an element of a with clause without RECURSIVE
specifier and the reference t belongs either to the unit to which this
with clause is attached or to one of the elements from this clause that
are placed before the definition of cte.
If a table reference can be resolved against several CTE definitions then
it is bound to the most embedded.
The code before this patch not always resolved table references used in
embedded CTE according to the above rules.
Approved by Oleksandr Byelkin <sanja@mariadb.com>
Diffstat (limited to 'sql/sql_cte.h')
-rw-r--r-- | sql/sql_cte.h | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/sql/sql_cte.h b/sql/sql_cte.h index 47071dd06fd..b2708186008 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -391,10 +391,24 @@ public: bool add_with_element(With_element *elem); /* Add this with clause to the list of with clauses used in the statement */ - void add_to_list(With_clause ** &last_next) + void add_to_list(With_clause **ptr, With_clause ** &last_next) { - *last_next= this; - last_next= &this->next_with_clause; + if (embedding_with_clause) + { + /* + An embedded with clause is always placed before the embedding one + in the list of with clauses used in the query. + */ + while (*ptr != embedding_with_clause) + ptr= &(*ptr)->next_with_clause; + *ptr= this; + next_with_clause= embedding_with_clause; + } + else + { + *last_next= this; + last_next= &this->next_with_clause; + } } void set_owner(st_select_lex_unit *unit) { owner= unit; } |