diff options
author | Igor Babaev <igor@askmonty.org> | 2023-01-19 21:43:29 +0100 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2023-01-20 09:07:02 +0100 |
commit | ea270178b09bb1e2e1131957e95f36cd1f611b22 (patch) | |
tree | 005a492ef0f4cc75b30a34709800256dc1443e51 | |
parent | 6fe882cd85aee487c0534e6399ebd16c1ad2cab4 (diff) | |
download | mariadb-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.result | 63 | ||||
-rw-r--r-- | mysql-test/main/win_orderby.test | 55 | ||||
-rw-r--r-- | sql/sql_lex.cc | 7 | ||||
-rw-r--r-- | sql/sql_lex.h | 8 | ||||
-rw-r--r-- | sql/sql_list.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 12 |
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 + |