MDEV-15057 Crash when using an unknown identifier as an SP parameter
It crashed because we accessed lex->current_select when it was a NULL, which is the case for SP parameters or local variables.
This commit is contained in:
parent
c269f1d6fe
commit
0dbe3dbe79
@ -8184,3 +8184,31 @@ END
|
|||||||
|
|
|
|
||||||
CALL p1();
|
CALL p1();
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
|
#
|
||||||
|
# MDEV-15057 Crash when using an unknown identifier as an SP parameter
|
||||||
|
#
|
||||||
|
CREATE OR REPLACE PROCEDURE p1 (a VARCHAR(10)) SELECT 1;
|
||||||
|
CALL p1(a);
|
||||||
|
ERROR 42S22: Unknown column 'a' in 'field list'
|
||||||
|
drop procedure p1;
|
||||||
|
CREATE OR REPLACE PROCEDURE p1 (a VARCHAR(10)) SELECT a|
|
||||||
|
CREATE OR REPLACE PROCEDURE p2 ()
|
||||||
|
BEGIN
|
||||||
|
DECLARE name VARCHAR(10);
|
||||||
|
SET name="hello";
|
||||||
|
call p1(name);
|
||||||
|
END|
|
||||||
|
CREATE OR REPLACE PROCEDURE p3 ()
|
||||||
|
BEGIN
|
||||||
|
DECLARE name VARCHAR(10);
|
||||||
|
SET name="hello";
|
||||||
|
call p1(name2);
|
||||||
|
END|
|
||||||
|
call p2();
|
||||||
|
a
|
||||||
|
hello
|
||||||
|
call p3();
|
||||||
|
ERROR 42S22: Unknown column 'name2' in 'field list'
|
||||||
|
drop procedure p1;
|
||||||
|
drop procedure p2;
|
||||||
|
drop procedure p3;
|
||||||
|
@ -9658,3 +9658,36 @@ DELIMITER ;|
|
|||||||
CALL p1();
|
CALL p1();
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-15057 Crash when using an unknown identifier as an SP parameter
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE p1 (a VARCHAR(10)) SELECT 1;
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
CALL p1(a);
|
||||||
|
drop procedure p1;
|
||||||
|
|
||||||
|
DELIMITER |;
|
||||||
|
|
||||||
|
CREATE OR REPLACE PROCEDURE p1 (a VARCHAR(10)) SELECT a|
|
||||||
|
CREATE OR REPLACE PROCEDURE p2 ()
|
||||||
|
BEGIN
|
||||||
|
DECLARE name VARCHAR(10);
|
||||||
|
SET name="hello";
|
||||||
|
call p1(name);
|
||||||
|
END|
|
||||||
|
CREATE OR REPLACE PROCEDURE p3 ()
|
||||||
|
BEGIN
|
||||||
|
DECLARE name VARCHAR(10);
|
||||||
|
SET name="hello";
|
||||||
|
call p1(name2);
|
||||||
|
END|
|
||||||
|
|
||||||
|
DELIMITER ;|
|
||||||
|
|
||||||
|
call p2();
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
call p3();
|
||||||
|
drop procedure p1;
|
||||||
|
drop procedure p2;
|
||||||
|
drop procedure p3;
|
||||||
|
34
sql/item.cc
34
sql/item.cc
@ -5132,7 +5132,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
*/
|
*/
|
||||||
Name_resolution_context *last_checked_context= context;
|
Name_resolution_context *last_checked_context= context;
|
||||||
Item **ref= (Item **) not_found_item;
|
Item **ref= (Item **) not_found_item;
|
||||||
SELECT_LEX *current_sel= (SELECT_LEX *) thd->lex->current_select;
|
SELECT_LEX *current_sel= thd->lex->current_select;
|
||||||
Name_resolution_context *outer_context= 0;
|
Name_resolution_context *outer_context= 0;
|
||||||
SELECT_LEX *select= 0;
|
SELECT_LEX *select= 0;
|
||||||
/* Currently derived tables cannot be correlated */
|
/* Currently derived tables cannot be correlated */
|
||||||
@ -5465,6 +5465,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
Field *from_field= (Field *)not_found_field;
|
Field *from_field= (Field *)not_found_field;
|
||||||
bool outer_fixed= false;
|
bool outer_fixed= false;
|
||||||
|
SELECT_LEX *select= thd->lex->current_select;
|
||||||
|
|
||||||
if (!field) // If field is not checked
|
if (!field) // If field is not checked
|
||||||
{
|
{
|
||||||
@ -5486,13 +5487,14 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
not_found_field)
|
not_found_field)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Look up in current select's item_list to find aliased fields */
|
/* Look up in current select's item_list to find aliased fields */
|
||||||
if (thd->lex->current_select->is_item_list_lookup)
|
if (select && select->is_item_list_lookup)
|
||||||
{
|
{
|
||||||
uint counter;
|
uint counter;
|
||||||
enum_resolution_type resolution;
|
enum_resolution_type resolution;
|
||||||
Item** res= find_item_in_list(this,
|
Item** res= find_item_in_list(this,
|
||||||
thd->lex->current_select->item_list,
|
select->item_list,
|
||||||
&counter, REPORT_EXCEPT_NOT_FOUND,
|
&counter, REPORT_EXCEPT_NOT_FOUND,
|
||||||
&resolution);
|
&resolution);
|
||||||
if (!res)
|
if (!res)
|
||||||
@ -5524,7 +5526,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
We can not "move" aggregate function in the place where
|
We can not "move" aggregate function in the place where
|
||||||
its arguments are not defined.
|
its arguments are not defined.
|
||||||
*/
|
*/
|
||||||
set_max_sum_func_level(thd, thd->lex->current_select);
|
set_max_sum_func_level(thd, select);
|
||||||
set_field(new_field);
|
set_field(new_field);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -5544,7 +5546,6 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
if (err)
|
if (err)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
SELECT_LEX *select= thd->lex->current_select;
|
|
||||||
thd->change_item_tree(reference,
|
thd->change_item_tree(reference,
|
||||||
select->context_analysis_place == IN_GROUP_BY &&
|
select->context_analysis_place == IN_GROUP_BY &&
|
||||||
alias_name_used ? *rf->ref : rf);
|
alias_name_used ? *rf->ref : rf);
|
||||||
@ -5553,11 +5554,17 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
We can not "move" aggregate function in the place where
|
We can not "move" aggregate function in the place where
|
||||||
its arguments are not defined.
|
its arguments are not defined.
|
||||||
*/
|
*/
|
||||||
set_max_sum_func_level(thd, thd->lex->current_select);
|
set_max_sum_func_level(thd, select);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!select)
|
||||||
|
{
|
||||||
|
my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
|
if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
outer_fixed= TRUE;
|
outer_fixed= TRUE;
|
||||||
@ -5586,9 +5593,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
|
|
||||||
if (thd->lex->in_sum_func &&
|
if (thd->lex->in_sum_func &&
|
||||||
thd->lex->in_sum_func->nest_level ==
|
thd->lex->in_sum_func->nest_level ==
|
||||||
thd->lex->current_select->nest_level)
|
select->nest_level)
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
||||||
thd->lex->current_select->nest_level);
|
select->nest_level);
|
||||||
/*
|
/*
|
||||||
if it is not expression from merged VIEW we will set this field.
|
if it is not expression from merged VIEW we will set this field.
|
||||||
|
|
||||||
@ -5654,11 +5661,12 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
fix_session_vcol_expr_for_read(thd, field, field->vcol_info);
|
fix_session_vcol_expr_for_read(thd, field, field->vcol_info);
|
||||||
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
|
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
|
||||||
!outer_fixed && !thd->lex->in_sum_func &&
|
!outer_fixed && !thd->lex->in_sum_func &&
|
||||||
thd->lex->current_select->cur_pos_in_select_list != UNDEF_POS &&
|
select &&
|
||||||
thd->lex->current_select->join)
|
select->cur_pos_in_select_list != UNDEF_POS &&
|
||||||
|
select->join)
|
||||||
{
|
{
|
||||||
thd->lex->current_select->join->non_agg_fields.push_back(this, thd->mem_root);
|
select->join->non_agg_fields.push_back(this, thd->mem_root);
|
||||||
marker= thd->lex->current_select->cur_pos_in_select_list;
|
marker= select->cur_pos_in_select_list;
|
||||||
}
|
}
|
||||||
mark_non_agg_field:
|
mark_non_agg_field:
|
||||||
/*
|
/*
|
||||||
@ -5695,7 +5703,7 @@ mark_non_agg_field:
|
|||||||
if (outer_fixed)
|
if (outer_fixed)
|
||||||
thd->lex->in_sum_func->outer_fields.push_back(this, thd->mem_root);
|
thd->lex->in_sum_func->outer_fields.push_back(this, thd->mem_root);
|
||||||
else if (thd->lex->in_sum_func->nest_level !=
|
else if (thd->lex->in_sum_func->nest_level !=
|
||||||
thd->lex->current_select->nest_level)
|
select->nest_level)
|
||||||
select_lex->set_non_agg_field_used(true);
|
select_lex->set_non_agg_field_used(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2881,6 +2881,7 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
|
|||||||
result of previous parsing.
|
result of previous parsing.
|
||||||
*/
|
*/
|
||||||
thd->lex->current_select= NULL;
|
thd->lex->current_select= NULL;
|
||||||
|
thd->lex->in_sum_func= 0; // For Item_field::fix_fields()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We never write CALL statements into binlog:
|
We never write CALL statements into binlog:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user