mirror of
https://github.com/MariaDB/server.git
synced 2025-07-26 07:02:12 +03:00
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>
This commit is contained in:
@ -751,3 +751,19 @@ REPLACE INTO v1 SET f = NULL;
|
|||||||
ERROR 22007: Truncated incorrect DOUBLE value: 'foo'
|
ERROR 22007: Truncated incorrect DOUBLE value: 'foo'
|
||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1;
|
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
|
||||||
|
@ -612,3 +612,25 @@ CREATE VIEW v1 AS SELECT * FROM t1 WHERE f <=> 'foo' WITH CHECK OPTION;
|
|||||||
REPLACE INTO v1 SET f = NULL;
|
REPLACE INTO v1 SET f = NULL;
|
||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1;
|
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
|
||||||
|
@ -701,6 +701,7 @@ void LEX::start(THD *thd_arg)
|
|||||||
context_stack.empty();
|
context_stack.empty();
|
||||||
//empty select_stack
|
//empty select_stack
|
||||||
select_stack_top= 0;
|
select_stack_top= 0;
|
||||||
|
select_stack_outer_barrier= 0;
|
||||||
unit.init_query();
|
unit.init_query();
|
||||||
current_select_number= 0;
|
current_select_number= 0;
|
||||||
curr_with_clause= 0;
|
curr_with_clause= 0;
|
||||||
|
@ -3246,6 +3246,12 @@ public:
|
|||||||
List<Name_resolution_context> context_stack;
|
List<Name_resolution_context> context_stack;
|
||||||
SELECT_LEX *select_stack[MAX_SELECT_NESTING + 1];
|
SELECT_LEX *select_stack[MAX_SELECT_NESTING + 1];
|
||||||
uint select_stack_top;
|
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<ORDER> proc_list;
|
||||||
SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list;
|
SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list;
|
||||||
@ -3686,6 +3692,17 @@ public:
|
|||||||
|
|
||||||
bool copy_db_to(LEX_CSTRING *to);
|
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()
|
Name_resolution_context *current_context()
|
||||||
{
|
{
|
||||||
return context_stack.head();
|
return context_stack.head();
|
||||||
|
@ -9015,9 +9015,7 @@ push_new_name_resolution_context(THD *thd,
|
|||||||
right_op->last_leaf_for_name_resolution();
|
right_op->last_leaf_for_name_resolution();
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
on_context->select_lex = lex->current_select;
|
on_context->select_lex = lex->current_select;
|
||||||
st_select_lex *curr_select= lex->pop_select();
|
st_select_lex *outer_sel= lex->parser_current_outer_select();
|
||||||
st_select_lex *outer_sel= lex->select_stack_head();
|
|
||||||
lex->push_select(curr_select);
|
|
||||||
on_context->outer_context = outer_sel ? &outer_sel->context : 0;
|
on_context->outer_context = outer_sel ? &outer_sel->context : 0;
|
||||||
return lex->push_context(on_context);
|
return lex->push_context(on_context);
|
||||||
}
|
}
|
||||||
|
@ -13608,6 +13608,7 @@ insert:
|
|||||||
if (Lex->main_select_push())
|
if (Lex->main_select_push())
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
mysql_init_select(lex);
|
mysql_init_select(lex);
|
||||||
|
lex->inc_select_stack_outer_barrier();
|
||||||
lex->current_select->parsing_place= BEFORE_OPT_LIST;
|
lex->current_select->parsing_place= BEFORE_OPT_LIST;
|
||||||
}
|
}
|
||||||
insert_lock_option
|
insert_lock_option
|
||||||
@ -13634,6 +13635,7 @@ replace:
|
|||||||
if (Lex->main_select_push())
|
if (Lex->main_select_push())
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
mysql_init_select(lex);
|
mysql_init_select(lex);
|
||||||
|
lex->inc_select_stack_outer_barrier();
|
||||||
lex->current_select->parsing_place= BEFORE_OPT_LIST;
|
lex->current_select->parsing_place= BEFORE_OPT_LIST;
|
||||||
}
|
}
|
||||||
replace_lock_option insert2
|
replace_lock_option insert2
|
||||||
|
Reference in New Issue
Block a user