Commit f564ceb4 authored by Alexander Barkov's avatar Alexander Barkov

Fixed a crash in a EXIT/CONTINUE with an unknown identifier in the WHEN clause

The crash happened because of a wrong reset_lex() .. restore_lex() sequence.
The Item in WHERE clause and the corresponding sp_instr_jump_if_not() were
erroneously created using different LEX.
parent cfb63459
......@@ -1021,3 +1021,48 @@ SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
f1(3) f1(4) f1(5) f1(6)
3 4 4 5
DROP FUNCTION f1;
#
# Testing behaviour of unknown identifiers in EXIT and CONTINUE statements
#
CREATE PROCEDURE p1
AS
BEGIN
LOOP
EXIT WHEN unknown_ident IS NULL;
END LOOP;
END$$
CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
BEGIN
<<label>>
LOOP
EXIT label WHEN unknown_ident IS NULL;
END LOOP;
END$$
CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
BEGIN
LOOP
CONTINUE WHEN unknown_ident IS NULL;
END LOOP;
END$$
CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
BEGIN
<<label>>
LOOP
CONTINUE label WHEN unknown_ident IS NULL;
END LOOP;
END$$
CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
DROP PROCEDURE p1;
......@@ -1097,3 +1097,64 @@ END;
DELIMITER ;/
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
DROP FUNCTION f1;
--echo #
--echo # Testing behaviour of unknown identifiers in EXIT and CONTINUE statements
--echo #
DELIMITER $$;
CREATE PROCEDURE p1
AS
BEGIN
LOOP
EXIT WHEN unknown_ident IS NULL;
END LOOP;
END$$
DELIMITER ;$$
--error ER_BAD_FIELD_ERROR
CALL p1;
DROP PROCEDURE p1;
DELIMITER $$;
CREATE PROCEDURE p1
AS
BEGIN
<<label>>
LOOP
EXIT label WHEN unknown_ident IS NULL;
END LOOP;
END$$
DELIMITER ;$$
--error ER_BAD_FIELD_ERROR
CALL p1;
DROP PROCEDURE p1;
DELIMITER $$;
CREATE PROCEDURE p1
AS
BEGIN
LOOP
CONTINUE WHEN unknown_ident IS NULL;
END LOOP;
END$$
DELIMITER ;$$
--error ER_BAD_FIELD_ERROR
CALL p1;
DROP PROCEDURE p1;
DELIMITER $$;
CREATE PROCEDURE p1
AS
BEGIN
<<label>>
LOOP
CONTINUE label WHEN unknown_ident IS NULL;
END LOOP;
END$$
DELIMITER ;$$
--error ER_BAD_FIELD_ERROR
CALL p1;
DROP PROCEDURE p1;
......@@ -5637,7 +5637,6 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
if (!when)
return sp_exit_block(thd, lab);
sphead->reset_lex(thd); // This changes thd->lex
DBUG_ASSERT(sphead == thd->lex->sphead);
DBUG_ASSERT(spcont == thd->lex->spcont);
sp_instr_jump_if_not *i= new (thd->mem_root)
......@@ -5646,7 +5645,6 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
when, thd->lex);
if (i == NULL ||
sphead->add_instr(i) ||
sphead->restore_lex(thd) ||
sp_exit_block(thd, lab))
return true;
i->backpatch(sphead->instructions(), spcont);
......@@ -5712,7 +5710,6 @@ bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
if (!when)
return sp_continue_loop(thd, lab);
sphead->reset_lex(thd); // This changes thd->lex
DBUG_ASSERT(sphead == thd->lex->sphead);
DBUG_ASSERT(spcont == thd->lex->spcont);
sp_instr_jump_if_not *i= new (thd->mem_root)
......@@ -5721,7 +5718,6 @@ bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
when, thd->lex);
if (i == NULL ||
sphead->add_instr(i) ||
sphead->restore_lex(thd) ||
sp_continue_loop(thd, lab))
return true;
i->backpatch(sphead->instructions(), spcont);
......
......@@ -1097,7 +1097,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
signal_allowed_expr
simple_target_specification
condition_number
opt_sp_proc_stmt_exit_when_clause
reset_lex_expr
%type <item_param> param_marker
......@@ -2988,33 +2988,56 @@ sp_proc_stmt_return:
}
;
opt_sp_proc_stmt_exit_when_clause:
/* Empty */ { $$= NULL; }
| WHEN_SYM expr { $$= $2; }
reset_lex_expr:
{ Lex->sphead->reset_lex(thd); } expr { $$= $2; }
;
sp_proc_stmt_exit:
EXIT_SYM opt_sp_proc_stmt_exit_when_clause
EXIT_SYM
{
if (Lex->sp_exit_statement(thd, $2))
if (Lex->sp_exit_statement(thd, NULL))
MYSQL_YYABORT;
}
| EXIT_SYM label_ident opt_sp_proc_stmt_exit_when_clause
| EXIT_SYM label_ident
{
if (Lex->sp_exit_statement(thd, $2, $3))
if (Lex->sp_exit_statement(thd, $2, NULL))
MYSQL_YYABORT;
}
| EXIT_SYM WHEN_SYM reset_lex_expr
{
if (Lex->sp_exit_statement(thd, $3) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
| EXIT_SYM label_ident WHEN_SYM reset_lex_expr
{
if (Lex->sp_exit_statement(thd, $2, $4) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
sp_proc_stmt_continue:
CONTINUE_SYM opt_sp_proc_stmt_exit_when_clause
CONTINUE_SYM
{
if (Lex->sp_continue_statement(thd, NULL))
MYSQL_YYABORT;
}
| CONTINUE_SYM label_ident
{
if (Lex->sp_continue_statement(thd, $2, NULL))
MYSQL_YYABORT;
}
| CONTINUE_SYM WHEN_SYM reset_lex_expr
{
if (Lex->sp_continue_statement(thd, $2))
if (Lex->sp_continue_statement(thd, $3) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
| CONTINUE_SYM label_ident opt_sp_proc_stmt_exit_when_clause
| CONTINUE_SYM label_ident WHEN_SYM reset_lex_expr
{
if (Lex->sp_continue_statement(thd, $2, $3))
if (Lex->sp_continue_statement(thd, $2, $4) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment