[Commits] f04bf35: MDEV-26412 Server crash in Item_field::fix_outer_field for INSERT SELECT
revision-id: f04bf3529cbe472c6d73158e9bc73b1a5e8c1841 (mariadb-10.4.23-34-gf04bf35) parent(s): c519aa3d7aea1afb7754ccf70aa5b276ff5fbf87 author: Igor Babaev committer: Igor Babaev timestamp: 2022-04-25 18:08:57 -0700 message: MDEV-26412 Server crash in Item_field::fix_outer_field for INSERT SELECT IF an INSERT/REPLACE SELECT statement contained an ON expression in the top level select and this expression used a subquery with a column reference that could not be resolved then an attempt to resolve this reference as an outer reference caused a crash of the server. This happened because the outer context field in the Name_resolution_context structure was not set to NULL for such references. Rather it pointed to the first element in the select_stack. Note that starting from 10.4 we cannot use the SELECT_LEX::outer_select() method when parsing a SELECT construct. Approved by Oleksandr Byelkin <sanja@mariadb.com> --- mysql-test/main/insert.result | 16 ++++++++++++++++ mysql-test/main/insert.test | 22 ++++++++++++++++++++++ sql/sql_lex.cc | 1 + sql/sql_lex.h | 17 +++++++++++++++++ sql/sql_parse.cc | 4 +--- sql/sql_yacc.yy | 2 ++ 6 files changed, 59 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/insert.result b/mysql-test/main/insert.result index 4aea812..1062ddd 100644 --- a/mysql-test/main/insert.result +++ b/mysql-test/main/insert.result @@ -751,3 +751,19 @@ REPLACE INTO v1 SET f = NULL; ERROR 22007: Truncated incorrect DOUBLE value: 'foo' DROP VIEW v1; DROP TABLE t1; +# End of 10.0 tests +# +# MDEV-26412: INSERT CREATE with subquery in ON expression +# +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create table t4 (d1 int, d2 int); +insert into t4 +select * from t1 left join t2 on (select t1.i from t3); +ERROR 42S22: Unknown column 't1.i' in 'field list' +replace t4 +select * from t1 left join t2 on (select t1.i from t3); +ERROR 42S22: Unknown column 't1.i' in 'field list' +drop table t1,t2,t3,t4; +# End of 10.4 tests diff --git a/mysql-test/main/insert.test b/mysql-test/main/insert.test index e00c9cd..9fd0933 100644 --- a/mysql-test/main/insert.test +++ b/mysql-test/main/insert.test @@ -612,3 +612,25 @@ CREATE VIEW v1 AS SELECT * FROM t1 WHERE f <=> 'foo' WITH CHECK OPTION; REPLACE INTO v1 SET f = NULL; DROP VIEW v1; DROP TABLE t1; + +--echo # End of 10.0 tests + +--echo # +--echo # MDEV-26412: INSERT CREATE with subquery in ON expression +--echo # + +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create table t4 (d1 int, d2 int); + +--error ER_BAD_FIELD_ERROR +insert into t4 + select * from t1 left join t2 on (select t1.i from t3); +--error ER_BAD_FIELD_ERROR +replace t4 + select * from t1 left join t2 on (select t1.i from t3); + +drop table t1,t2,t3,t4; + +--echo # End of 10.4 tests diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a93652c..b8f009f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -701,6 +701,7 @@ void LEX::start(THD *thd_arg) context_stack.empty(); //empty select_stack select_stack_top= 0; + select_stack_outer_barrier= 0; unit.init_query(); current_select_number= 0; curr_with_clause= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 19d4eb0..f274695 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3246,6 +3246,12 @@ struct LEX: public Query_tables_list List<Name_resolution_context> context_stack; SELECT_LEX *select_stack[MAX_SELECT_NESTING + 1]; uint select_stack_top; + /* + Usually this is set to 0, but for INSERT/REPLACE SELECT it is set to 1. + When parsing such statements the pointer to the most outer select is placed + into the second element of select_stack rather than into the first. + */ + uint select_stack_outer_barrier; SQL_I_List<ORDER> proc_list; SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list; @@ -3686,6 +3692,17 @@ struct LEX: public Query_tables_list bool copy_db_to(LEX_CSTRING *to); + void inc_select_stack_outer_barrier() + { + select_stack_outer_barrier++; + } + + SELECT_LEX *parser_current_outer_select() + { + return select_stack_top - 1 == select_stack_outer_barrier ? + 0 : select_stack[select_stack_top - 1]; + } + Name_resolution_context *current_context() { return context_stack.head(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 35310d2..723f072 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -9015,9 +9015,7 @@ push_new_name_resolution_context(THD *thd, right_op->last_leaf_for_name_resolution(); LEX *lex= thd->lex; on_context->select_lex = lex->current_select; - st_select_lex *curr_select= lex->pop_select(); - st_select_lex *outer_sel= lex->select_stack_head(); - lex->push_select(curr_select); + st_select_lex *outer_sel= lex->parser_current_outer_select(); on_context->outer_context = outer_sel ? &outer_sel->context : 0; return lex->push_context(on_context); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index fed704e..ddb3604 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -13579,6 +13579,7 @@ insert: if (Lex->main_select_push()) MYSQL_YYABORT; mysql_init_select(lex); + lex->inc_select_stack_outer_barrier(); lex->current_select->parsing_place= BEFORE_OPT_LIST; } insert_lock_option @@ -13605,6 +13606,7 @@ replace: if (Lex->main_select_push()) MYSQL_YYABORT; mysql_init_select(lex); + lex->inc_select_stack_outer_barrier(); lex->current_select->parsing_place= BEFORE_OPT_LIST; } replace_lock_option insert2
participants (1)
-
IgorBabaev