summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2021-05-16 12:30:40 +0300
committerSergei Petrunia <psergey@askmonty.org>2021-05-16 12:30:40 +0300
commit9317dc96f03f558dc20d41f7dcf003e6ebf6a2b4 (patch)
tree6b6ef8af628555b830157e2962f11c6662a404c1
parentbee1bb056dd5350c967dda65efb75e3a171e649a (diff)
downloadmariadb-git-bb-10.6-mdev25631.tar.gz
MDEV-25631: Crash in st_select_lex::mark_as_dependent with VIEW, aggregate and subquerybb-10.6-mdev25631
Name resolution code has checks like this one: if (thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level >= select->nest_level) ... This fails to take into account the fact SELECT_LEX::nest_level is local to each VIEW. Adjust the check so that it only succeeds when the select and the aggregate function being considered are from the same VIEW (or both from the top-level query): add this: + thd->lex->in_sum_func->nest_level_base == select->nest_level_base && Note: this patch only modifies one such check. There are many, should they all be adjusted in the same way?
-rw-r--r--mysql-test/main/subselect4.result11
-rw-r--r--mysql-test/main/subselect4.test15
-rw-r--r--sql/item.cc3
-rw-r--r--sql/item_sum.cc1
-rw-r--r--sql/item_sum.h1
5 files changed, 31 insertions, 0 deletions
diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result
index 3bfb755120b..182235c039b 100644
--- a/mysql-test/main/subselect4.result
+++ b/mysql-test/main/subselect4.result
@@ -2898,3 +2898,14 @@ id select_type table type possible_keys key key_len ref rows Extra
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 100
drop table t0, t1, t2;
# End of 10.4 tests
+#
+# MDEV-25631: Crash in st_select_lex::mark_as_dependent with VIEW, aggregate and subquery
+#
+CREATE TABLE t1 (i1 int);
+insert into t1 values (1),(2),(3);
+CREATE VIEW v1 AS
+SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b)));
+SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
+ERROR 21000: Subquery returns more than 1 row
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test
index a1a4108de37..bd18ec5f5c9 100644
--- a/mysql-test/main/subselect4.test
+++ b/mysql-test/main/subselect4.test
@@ -2398,3 +2398,18 @@ select * from t1 where t1.a in (select t2.a from t2 order by t2.b);
drop table t0, t1, t2;
--echo # End of 10.4 tests
+
+--echo #
+--echo # MDEV-25631: Crash in st_select_lex::mark_as_dependent with VIEW, aggregate and subquery
+--echo #
+
+CREATE TABLE t1 (i1 int);
+insert into t1 values (1),(2),(3); #not important
+CREATE VIEW v1 AS
+SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b)));
+
+--error ER_SUBQUERY_NO_1_ROW
+SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
+
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/sql/item.cc b/sql/item.cc
index 5cdbf52e829..a4c16c53e5e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5608,9 +5608,12 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
max_arg_level for the function if it's needed.
*/
if (thd->lex->in_sum_func &&
+ thd->lex->in_sum_func->nest_level_base == select->nest_level_base &&
thd->lex->in_sum_func->nest_level >= select->nest_level)
{
Item::Type ref_type= (*reference)->type();
+ // psergey-todo: check if in_sum_func "has" the same
+ // nest_level_base as we do..
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
select->nest_level);
set_field(*from_field);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 537eaaf8dcd..23b6f739333 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -92,6 +92,7 @@ bool Item_sum::init_sum_func_check(THD *thd)
/* Save a pointer to object to be used in items for nested set functions */
thd->lex->in_sum_func= this;
nest_level= thd->lex->current_select->nest_level;
+ nest_level_base= thd->lex->current_select->nest_level_base;
ref_by= 0;
aggr_level= -1;
aggr_sel= NULL;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 118f78ec5c1..10aa658c5e2 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -364,6 +364,7 @@ public:
Item_sum *in_sum_func; /* embedding set function if any */
st_select_lex * aggr_sel; /* select where the function is aggregated */
int8 nest_level; /* number of the nesting level of the set function */
+ st_select_lex_unit *nest_level_base;
int8 aggr_level; /* nesting level of the aggregating subquery */
int8 max_arg_level; /* max level of unbound column references */
int8 max_sum_func_level;/* max level of aggregation for embedded functions */