[Commits] 9317dc96f03: MDEV-25631: Crash in st_select_lex::mark_as_dependent with VIEW, aggregate and subquery

psergey sergey at mariadb.com
Sun May 16 12:31:19 EEST 2021


revision-id: 9317dc96f03f558dc20d41f7dcf003e6ebf6a2b4 (mariadb-10.6.0-52-g9317dc96f03)
parent(s): bee1bb056dd5350c967dda65efb75e3a171e649a
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2021-05-16 12:30:40 +0300
message:

MDEV-25631: Crash in st_select_lex::mark_as_dependent with VIEW, aggregate and subquery

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?

---
 mysql-test/main/subselect4.result | 11 +++++++++++
 mysql-test/main/subselect4.test   | 15 +++++++++++++++
 sql/item.cc                       |  3 +++
 sql/item_sum.cc                   |  1 +
 sql/item_sum.h                    |  1 +
 5 files changed, 31 insertions(+)

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 @@ class Item_sum :public Item_func_or_sum
   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 */


More information about the commits mailing list