[Commits] 5289376: MDEV-25484 Crash when parsing query using derived table containing TVC

IgorBabaev igor at mariadb.com
Thu Jul 22 21:21:39 EEST 2021


revision-id: 528937607f8da8b99ef72d28ead839d7f319b980 (mariadb-10.3.26-206-g5289376)
parent(s): 6190a02f3593f82e2d4916ed660afb5e5d631a5a
author: Igor Babaev
committer: Igor Babaev
timestamp: 2021-07-22 11:21:39 -0700
message:

MDEV-25484 Crash when parsing query using derived table containing TVC

This patch fixes parsing problems concerning derived tables that use table
value constructors (TVC) with LIMIT and ORDER BY clauses of the form
  ((VALUES ... LIMIT ...) ORDER BY ...) as dt
The fix has to be applied only to 10.3 as 10.4 that employs a different
grammar rules has no such problems. The test cases should be merged
upstream.

Approved by Oleksandr Byelkin <sanja at mariadb.com>

---
 mysql-test/main/table_value_constr.test | 22 ++++++++++++++++++++++
 sql/sql_lex.cc                          |  9 ++++++++-
 sql/sql_yacc.yy                         | 12 ++++++++----
 3 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test
index 3e976f8..d139625 100644
--- a/mysql-test/main/table_value_constr.test
+++ b/mysql-test/main/table_value_constr.test
@@ -1628,4 +1628,26 @@ select * from t1;
 
 drop table t1;
 
+
+--echo #
+--echo # MDEV-25484: Derived table using TVC with LIMIT and ORDER BY
+--echo #
+
+create table t1 (a int);
+insert into t1 values (3), (7), (1);
+
+select * from ( (select * from t1 limit 2) order by 1 desc) as dt;
+(values (3), (7), (1) limit 2) order by 1 desc;
+select * from ( (values (3), (7), (1) limit 2) order by 1 desc) as dt;
+
+
+select * from ( select * from t1 order by 1 limit 2 ) as dt;
+values (3),(7),(1) order by 1 limit 2;
+select * from ( values (3),(7),(1) order by 1 limit 2 ) as dt;
+
+values (3),(7),(1) union values (2),(4) order by 1 limit 2;
+select * from (values (3),(7),(1) union values (2),(4) order by 1 limit 2) as dt;
+
+drop table t1;
+
 --echo End of 10.3 tests
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 2a337b0..8de645a 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -8396,8 +8396,15 @@ bool LEX::tvc_finalize_derived()
     thd->parse_error();
     return true;
   }
+  if (unlikely(!(current_select->tvc=
+               new (thd->mem_root)
+               table_value_constr(many_values,
+                                  current_select,
+                                  current_select->options))))
+    return true;
+  restore_values_list_state();
   current_select->linkage= DERIVED_TABLE_TYPE;
-  return tvc_finalize();
+  return false;
 }
 
 
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index b915667..7d13dd8 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -12855,10 +12855,13 @@ order_clause:
                 created yet.
               */
               SELECT_LEX *first_sl= unit->first_select();
-              if (unlikely(!unit->is_unit_op() &&
-                          (first_sl->order_list.elements ||
-                           first_sl->select_limit) &&
+              if (unlikely(!first_sl->next_select() && first_sl->tvc &&
                            unit->add_fake_select_lex(thd)))
+                 MYSQL_YYABORT;
+              else if (unlikely(!unit->is_unit_op() &&
+                                (first_sl->order_list.elements ||
+                                 first_sl->select_limit) &&
+                                unit->add_fake_select_lex(thd)))
                 MYSQL_YYABORT;
             }
             if (sel->master_unit()->is_unit_op() && !sel->braces)
@@ -12907,7 +12910,8 @@ limit_clause_init:
           LIMIT
           {
             SELECT_LEX *sel= Select;
-            if (sel->master_unit()->is_unit_op() && !sel->braces)
+            if (sel->master_unit()->is_unit_op() && !sel->braces &&
+                sel->master_unit()->fake_select_lex)
             {
               /* Move LIMIT that belongs to UNION to fake_select_lex */
               Lex->current_select= sel->master_unit()->fake_select_lex;


More information about the commits mailing list