Commit 4e9e038f authored by pem@mysql.com's avatar pem@mysql.com

Fixed BUG#14376: MySQL crash on scoped variable (re)initialization

  Added finer scope control for default clauses of local variable
  declarations.
parent 69cd4c1e
...@@ -3575,4 +3575,33 @@ DROP VIEW bug13095_v1 ...@@ -3575,4 +3575,33 @@ DROP VIEW bug13095_v1
DROP PROCEDURE IF EXISTS bug13095; DROP PROCEDURE IF EXISTS bug13095;
DROP VIEW IF EXISTS bug13095_v1; DROP VIEW IF EXISTS bug13095_v1;
DROP TABLE IF EXISTS bug13095_t1; DROP TABLE IF EXISTS bug13095_t1;
drop procedure if exists bug14376|
create procedure bug14376()
begin
declare x int default x;
end|
call bug14376()|
ERROR 42S22: Unknown column 'x' in 'field list'
drop procedure bug14376|
create procedure bug14376()
begin
declare x int default 42;
begin
declare x int default x;
select x;
end;
end|
call bug14376()|
x
42
drop procedure bug14376|
create procedure bug14376(x int)
begin
declare x int default x;
select x;
end|
call bug14376(4711)|
x
4711
drop procedure bug14376|
drop table t1,t2; drop table t1,t2;
...@@ -4489,6 +4489,51 @@ DROP TABLE IF EXISTS bug13095_t1; ...@@ -4489,6 +4489,51 @@ DROP TABLE IF EXISTS bug13095_t1;
delimiter |; delimiter |;
#
# BUG#14376: MySQL crash on scoped variable (re)initialization
#
--disable_warnings
drop procedure if exists bug14376|
--enable_warnings
create procedure bug14376()
begin
declare x int default x;
end|
# Not the error we want, but that's what we got for now...
--error ER_BAD_FIELD_ERROR
call bug14376()|
drop procedure bug14376|
create procedure bug14376()
begin
declare x int default 42;
begin
declare x int default x;
select x;
end;
end|
call bug14376()|
drop procedure bug14376|
create procedure bug14376(x int)
begin
declare x int default x;
select x;
end|
call bug14376(4711)|
drop procedure bug14376|
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
......
...@@ -52,7 +52,7 @@ sp_cond_check(LEX_STRING *sqlstate) ...@@ -52,7 +52,7 @@ sp_cond_check(LEX_STRING *sqlstate)
sp_pcontext::sp_pcontext(sp_pcontext *prev) sp_pcontext::sp_pcontext(sp_pcontext *prev)
: Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0), : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0),
m_handlers(0), m_parent(prev) m_handlers(0), m_parent(prev), m_pboundary(0)
{ {
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8)); VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8)); VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
...@@ -150,7 +150,7 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx) ...@@ -150,7 +150,7 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx)
sp_pvar_t * sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped) sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
{ {
uint i= m_pvar.elements; uint i= m_pboundary;
while (i--) while (i--)
{ {
...@@ -186,6 +186,7 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type, ...@@ -186,6 +186,7 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
p->offset= current_pvars(); p->offset= current_pvars();
p->dflt= NULL; p->dflt= NULL;
insert_dynamic(&m_pvar, (gptr)&p); insert_dynamic(&m_pvar, (gptr)&p);
m_pboundary= m_pvar.elements;
} }
} }
......
...@@ -164,6 +164,7 @@ class sp_pcontext : public Sql_alloc ...@@ -164,6 +164,7 @@ class sp_pcontext : public Sql_alloc
{ {
while (num--) while (num--)
pop_dynamic(&m_pvar); pop_dynamic(&m_pvar);
m_pboundary= m_pvar.elements;
} }
// Find by name // Find by name
...@@ -183,6 +184,14 @@ class sp_pcontext : public Sql_alloc ...@@ -183,6 +184,14 @@ class sp_pcontext : public Sql_alloc
return p; return p;
} }
// Set the current scope boundary (for default values)
// The argument is the number of variables to skip.
inline void
declare_var_boundary(uint n)
{
m_pboundary= m_pvar.elements-n;
}
// //
// Labels // Labels
// //
...@@ -287,6 +296,13 @@ private: ...@@ -287,6 +296,13 @@ private:
uint m_poffset; // Variable offset for this context uint m_poffset; // Variable offset for this context
uint m_coffset; // Cursor offset for this context uint m_coffset; // Cursor offset for this context
/*
Boundary for finding variables in this in this context.
This is normally the same as m_pvar.elements, but differs during
parsing of DECLARE ... DEFAULT, to get the scope right for DEFAULT
values.
*/
uint m_pboundary;
DYNAMIC_ARRAY m_pvar; // Parameters/variables DYNAMIC_ARRAY m_pvar; // Parameters/variables
DYNAMIC_ARRAY m_cond; // Conditions DYNAMIC_ARRAY m_cond; // Conditions
......
...@@ -1660,7 +1660,12 @@ sp_decls: ...@@ -1660,7 +1660,12 @@ sp_decls:
sp_decl: sp_decl:
DECLARE_SYM sp_decl_idents type DECLARE_SYM sp_decl_idents type
{ Lex->sphead->reset_lex(YYTHD); } {
LEX *lex= Lex;
lex->sphead->reset_lex(YYTHD);
lex->spcont->declare_var_boundary($2);
}
sp_opt_default sp_opt_default
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -1690,6 +1695,7 @@ sp_decl: ...@@ -1690,6 +1695,7 @@ sp_decl:
lex->sphead->add_instr(in); lex->sphead->add_instr(in);
ctx->set_default(i, it); ctx->set_default(i, it);
} }
ctx->declare_var_boundary(0);
lex->sphead->restore_lex(YYTHD); lex->sphead->restore_lex(YYTHD);
$$.vars= $2; $$.vars= $2;
$$.conds= $$.hndlrs= $$.curs= 0; $$.conds= $$.hndlrs= $$.curs= 0;
......
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