summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2005-11-01 14:58:52 +0100
committerunknown <pem@mysql.com>2005-11-01 14:58:52 +0100
commit2c4c542ba2a82d42d3109f5257d0323e99bb321d (patch)
treed8e18d83d387b0b8b5cfd092973e6441f0ccec8a
parent389018280db5fab79ec76fb286071734b014fc0e (diff)
downloadmariadb-git-2c4c542ba2a82d42d3109f5257d0323e99bb321d.tar.gz
Fixed BUG#14376: MySQL crash on scoped variable (re)initialization
Added finer scope control for default clauses of local variable declarations. mysql-test/r/sp.result: New test case for BUG#14376. mysql-test/t/sp.test: New test case for BUG#14376. sql/sp_pcontext.cc: Added boundary variable for local parameters/variables, for better scope control of default values. sql/sp_pcontext.h: Added boundary variable for local parameters/variables, for better scope control of default values. sql/sql_yacc.yy: Make the variables of the current DECLARE "invisible" to its DEFAULT clause.
-rw-r--r--mysql-test/r/sp.result29
-rw-r--r--mysql-test/t/sp.test45
-rw-r--r--sql/sp_pcontext.cc5
-rw-r--r--sql/sp_pcontext.h16
-rw-r--r--sql/sql_yacc.yy8
5 files changed, 100 insertions, 3 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 1f3f7dba7da..1e4d3de5dfa 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -3575,4 +3575,33 @@ DROP VIEW bug13095_v1
DROP PROCEDURE IF EXISTS bug13095;
DROP VIEW IF EXISTS bug13095_v1;
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;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index ab57139bb77..f1b76686c4a 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -4490,6 +4490,51 @@ 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
#
#--disable_warnings
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index f873b676925..cca3e03d69c 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -52,7 +52,7 @@ sp_cond_check(LEX_STRING *sqlstate)
sp_pcontext::sp_pcontext(sp_pcontext *prev)
: 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_cond, sizeof(sp_cond_type_t *), 16, 8));
@@ -150,7 +150,7 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx)
sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
{
- uint i= m_pvar.elements;
+ uint i= m_pboundary;
while (i--)
{
@@ -186,6 +186,7 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
p->offset= current_pvars();
p->dflt= NULL;
insert_dynamic(&m_pvar, (gptr)&p);
+ m_pboundary= m_pvar.elements;
}
}
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index bd2259cb6fb..fbeac37c058 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -164,6 +164,7 @@ class sp_pcontext : public Sql_alloc
{
while (num--)
pop_dynamic(&m_pvar);
+ m_pboundary= m_pvar.elements;
}
// Find by name
@@ -183,6 +184,14 @@ class sp_pcontext : public Sql_alloc
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
//
@@ -287,6 +296,13 @@ private:
uint m_poffset; // Variable 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_cond; // Conditions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 109dcd7e86a..c3c53b2f611 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1660,7 +1660,12 @@ sp_decls:
sp_decl:
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
{
LEX *lex= Lex;
@@ -1690,6 +1695,7 @@ sp_decl:
lex->sphead->add_instr(in);
ctx->set_default(i, it);
}
+ ctx->declare_var_boundary(0);
lex->sphead->restore_lex(YYTHD);
$$.vars= $2;
$$.conds= $$.hndlrs= $$.curs= 0;