From d98ac8511e39770ef3d8b42937c84e876d1459e7 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Sat, 26 Oct 2024 20:29:56 +0700 Subject: [PATCH] MDEV-26247 MariaDB Server SEGV on INSERT .. SELECT This problem occured for statements like `INSERT INTO t1 SELECT 1`, which do not have tables in the SELECT part. In such scenarios SELECT_LEX::insert_tables was not properly set at `setup_tables()`, and this led to either incorrect execution or a crash Reviewer: Oleksandr Byelkin --- mysql-test/main/insert_select.result | 49 ++++++++++++++++++++++++++++ mysql-test/main/insert_select.test | 35 ++++++++++++++++++++ sql/sql_base.cc | 18 +++++++--- sql/sql_insert.cc | 2 +- 4 files changed, 99 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result index 1f8c1f69b4b..35c7880fa5f 100644 --- a/mysql-test/main/insert_select.result +++ b/mysql-test/main/insert_select.result @@ -984,3 +984,52 @@ drop table t1, t2; # # End of 10.3 test # +# +# MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT +# +CREATE TABLE t1 (a int); +INSERT INTO t1 SELECT AVG(1); +SELECT * FROM t1; +a +1 +INSERT INTO t1 SELECT MIN(2) OVER (); +SELECT * FROM t1; +a +1 +2 +CREATE VIEW v1 AS SELECT * FROM t1 ORDER BY a; +INSERT INTO v1 SELECT SUM(3); +SELECT * FROM v1; +a +1 +2 +3 +INSERT INTO v1 SELECT * FROM v1; +SELECT * FROM t1; +a +1 +1 +2 +2 +3 +3 +INSERT INTO t1 SELECT * FROM v1; +SELECT * FROM t1; +a +1 +1 +1 +1 +2 +2 +2 +2 +3 +3 +3 +3 +DROP VIEW v1; +DROP TABLE t1; +# +# End of 10.5 test +# diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test index 7417bab9a61..0e9bd05a93e 100644 --- a/mysql-test/main/insert_select.test +++ b/mysql-test/main/insert_select.test @@ -559,3 +559,38 @@ drop table t1, t2; --echo # --echo # End of 10.3 test --echo # + +--echo # +--echo # MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT +--echo # + +CREATE TABLE t1 (a int); + +INSERT INTO t1 SELECT AVG(1); +--sorted_result +SELECT * FROM t1; + +INSERT INTO t1 SELECT MIN(2) OVER (); +--sorted_result +SELECT * FROM t1; + +CREATE VIEW v1 AS SELECT * FROM t1 ORDER BY a; + +INSERT INTO v1 SELECT SUM(3); +--sorted_result +SELECT * FROM v1; + +INSERT INTO v1 SELECT * FROM v1; +--sorted_result +SELECT * FROM t1; + +INSERT INTO t1 SELECT * FROM v1; +--sorted_result +SELECT * FROM t1; + +DROP VIEW v1; +DROP TABLE t1; + +--echo # +--echo # End of 10.5 test +--echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4f151d397d4..bcab54ac1ec 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7834,18 +7834,19 @@ bool setup_tables(THD *thd, Name_resolution_context *context, while ((table_list= ti++)) leaves.push_back(table_list, thd->mem_root); } - + + bool is_insert_tables_num_set= false; while ((table_list= ti++)) { TABLE *table= table_list->table; if (table) table->pos_in_table_list= table_list; - if (first_select_table && + if (select_insert && !is_insert_tables_num_set && table_list->top_table() == first_select_table) { /* new counting for SELECT of INSERT ... SELECT command */ - first_select_table= 0; - thd->lex->select_lex.insert_tables= tablenr; + thd->lex->first_select_lex()->insert_tables= tablenr; + is_insert_tables_num_set= true; tablenr= 0; } if(table_list->jtbm_subselect) @@ -7867,6 +7868,15 @@ bool setup_tables(THD *thd, Name_resolution_context *context, my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast(MAX_TABLES)); DBUG_RETURN(1); } + if (select_insert && !is_insert_tables_num_set) + { + /* + This happens for statements like `INSERT INTO t1 SELECT 1`, + when there are no tables in the SELECT part. + In this case all leaf tables belong to the INSERT part + */ + thd->lex->first_select_lex()->insert_tables= tablenr; + } } else { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0a08866c5fa..e1d87e29869 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1570,7 +1570,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, if (insert_into_view && !fields.elements) { thd->lex->empty_field_list_on_rset= 1; - if (!thd->lex->select_lex.leaf_tables.head()->table || + if (!thd->lex->first_select_lex()->leaf_tables.head()->table || table_list->is_multitable()) { my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),