summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2023-01-19 21:43:29 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2023-01-20 09:07:02 +0100
commitea270178b09bb1e2e1131957e95f36cd1f611b22 (patch)
tree005a492ef0f4cc75b30a34709800256dc1443e51
parent6fe882cd85aee487c0534e6399ebd16c1ad2cab4 (diff)
downloadmariadb-git-ea270178b09bb1e2e1131957e95f36cd1f611b22.tar.gz
MDEV-30052 Crash with a query containing nested WINDOW clauses
Use SELECT_LEX to save lists for ORDER BY and GROUP BY before parsing WINDOW clauses / specifications. This is needed for proper parsing of a nested WINDOW clause when a WINDOW clause is used in a subquery contained in another WINDOW clause. Fix assignment of empty SQL_I_List to another one (in case of empty list next shoud point on first).
-rw-r--r--mysql-test/main/win_orderby.result63
-rw-r--r--mysql-test/main/win_orderby.test55
-rw-r--r--sql/sql_lex.cc7
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_parse.cc12
6 files changed, 130 insertions, 17 deletions
diff --git a/mysql-test/main/win_orderby.result b/mysql-test/main/win_orderby.result
index bf4a40a4db3..1a9860c1c76 100644
--- a/mysql-test/main/win_orderby.result
+++ b/mysql-test/main/win_orderby.result
@@ -24,3 +24,66 @@ pk count(a) over (order by pk rows between 2 preceding and 2 following)
28 5
27 5
drop table t0,t1;
+#
+# MDEV-30052: Crash with a query containing nested WINDOW clauses
+#
+CREATE TABLE t1 (c INT);
+insert into t1 values (1),(2);
+UPDATE t1 SET c=1
+WHERE c=2
+ORDER BY
+(1 IN ((
+SELECT *
+FROM (SELECT * FROM t1) AS v1
+GROUP BY c
+WINDOW v2 AS (ORDER BY
+(SELECT *
+FROM t1
+GROUP BY c
+WINDOW v3 AS (PARTITION BY c)
+)
+)
+))
+);
+drop table t1;
+#
+# MDEV-29359: Server crashed with heap-use-after-free in
+# Field::is_null(long long) const (Just testcase)
+#
+CREATE TABLE t1 (id int);
+INSERT INTO t1 VALUES (-1),(0),(84);
+SELECT
+id IN (SELECT id
+FROM t1
+WINDOW w AS (ORDER BY (SELECT 1
+FROM t1
+WHERE
+EXISTS ( SELECT id
+FROM t1
+GROUP BY id
+WINDOW w2 AS (ORDER BY id)
+)
+)
+)
+)
+FROM t1;
+id IN (SELECT id
+FROM t1
+WINDOW w AS (ORDER BY (SELECT 1
+FROM t1
+WHERE
+EXISTS ( SELECT id
+FROM t1
+GROUP BY id
+WINDOW w2 AS (ORDER BY id)
+)
+)
+)
+)
+1
+1
+1
+DROP TABLE t1;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/main/win_orderby.test b/mysql-test/main/win_orderby.test
index 7f02a582ea0..65421fc095c 100644
--- a/mysql-test/main/win_orderby.test
+++ b/mysql-test/main/win_orderby.test
@@ -33,3 +33,58 @@ limit 4;
--disable_view_protocol
drop table t0,t1;
+
+
+--echo #
+--echo # MDEV-30052: Crash with a query containing nested WINDOW clauses
+--echo #
+
+CREATE TABLE t1 (c INT);
+insert into t1 values (1),(2);
+UPDATE t1 SET c=1
+WHERE c=2
+ORDER BY
+ (1 IN ((
+ SELECT *
+ FROM (SELECT * FROM t1) AS v1
+ GROUP BY c
+ WINDOW v2 AS (ORDER BY
+ (SELECT *
+ FROM t1
+ GROUP BY c
+ WINDOW v3 AS (PARTITION BY c)
+ )
+ )
+ ))
+ );
+drop table t1;
+
+--echo #
+--echo # MDEV-29359: Server crashed with heap-use-after-free in
+--echo # Field::is_null(long long) const (Just testcase)
+--echo #
+
+CREATE TABLE t1 (id int);
+INSERT INTO t1 VALUES (-1),(0),(84);
+
+SELECT
+ id IN (SELECT id
+ FROM t1
+ WINDOW w AS (ORDER BY (SELECT 1
+ FROM t1
+ WHERE
+ EXISTS ( SELECT id
+ FROM t1
+ GROUP BY id
+ WINDOW w2 AS (ORDER BY id)
+ )
+ )
+ )
+ )
+FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5e4c41fe42c..a9adfebff81 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -755,8 +755,6 @@ void LEX::start(THD *thd_arg)
stmt_var_list.empty();
proc_list.elements=0;
- save_group_list.empty();
- save_order_list.empty();
win_ref= NULL;
win_frame= NULL;
frame_top_bound= NULL;
@@ -2389,9 +2387,8 @@ void st_select_lex::init_select()
ftfunc_list_alloc.empty();
inner_sum_func_list= 0;
ftfunc_list= &ftfunc_list_alloc;
- order_list.elements= 0;
- order_list.first= 0;
- order_list.next= &order_list.first;
+ order_list.empty();
+
/* Set limit and offset to default values */
select_limit= 0; /* denotes the default limit = HA_POS_ERROR */
offset_limit= 0; /* denotes the default offset = 0 */
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index bdc8b5476b2..febe4cf459e 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -975,6 +975,7 @@ public:
group_list_ptrs, and re-establish the original list before each execution.
*/
SQL_I_List<ORDER> group_list;
+ SQL_I_List<ORDER> save_group_list;
Group_list_ptrs *group_list_ptrs;
List<Item> item_list; /* list of fields & expressions */
@@ -1040,6 +1041,7 @@ public:
const char *type; /* type of select for EXPLAIN */
SQL_I_List<ORDER> order_list; /* ORDER clause */
+ SQL_I_List<ORDER> save_order_list;
SQL_I_List<ORDER> gorder_list;
Item *select_limit, *offset_limit; /* LIMIT clause parameters */
@@ -1249,9 +1251,7 @@ public:
void set_lock_for_tables(thr_lock_type lock_type, bool for_update);
inline void init_order()
{
- order_list.elements= 0;
- order_list.first= 0;
- order_list.next= &order_list.first;
+ order_list.empty();
}
/*
This method created for reiniting LEX in mysql_admin_table() and can be
@@ -3215,8 +3215,6 @@ public:
}
- SQL_I_List<ORDER> save_group_list;
- SQL_I_List<ORDER> save_order_list;
LEX_CSTRING *win_ref;
Window_frame *win_frame;
Window_frame_bound *frame_top_bound;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index b11239856f5..e2b65dcad14 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -53,7 +53,7 @@ public:
{
elements= tmp.elements;
first= tmp.first;
- next= tmp.next;
+ next= elements ? tmp.next : &first;;
return *this;
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 3102aa69b86..f360b246cce 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -8662,8 +8662,8 @@ TABLE_LIST *st_select_lex::convert_right_join()
void st_select_lex::prepare_add_window_spec(THD *thd)
{
LEX *lex= thd->lex;
- lex->save_group_list= group_list;
- lex->save_order_list= order_list;
+ save_group_list= group_list;
+ save_order_list= order_list;
lex->win_ref= NULL;
lex->win_frame= NULL;
lex->frame_top_bound= NULL;
@@ -8690,8 +8690,8 @@ bool st_select_lex::add_window_def(THD *thd,
win_part_list_ptr,
win_order_list_ptr,
win_frame);
- group_list= thd->lex->save_group_list;
- order_list= thd->lex->save_order_list;
+ group_list= save_group_list;
+ order_list= save_order_list;
if (parsing_place != SELECT_LIST)
{
fields_in_window_functions+= win_part_list_ptr->elements +
@@ -8717,8 +8717,8 @@ bool st_select_lex::add_window_spec(THD *thd,
win_part_list_ptr,
win_order_list_ptr,
win_frame);
- group_list= thd->lex->save_group_list;
- order_list= thd->lex->save_order_list;
+ group_list= save_group_list;
+ order_list= save_order_list;
if (parsing_place != SELECT_LIST)
{
fields_in_window_functions+= win_part_list_ptr->elements +