summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp.result25
-rw-r--r--mysql-test/t/sp.test38
-rw-r--r--sql/sp_head.cc14
-rw-r--r--sql/sp_rcontext.cc9
-rw-r--r--sql/sp_rcontext.h12
5 files changed, 90 insertions, 8 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index ed858ba27ee..69ae64475d2 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -3224,4 +3224,29 @@ bbbbb 2
ccccc 3
drop procedure bug10136|
drop table t3|
+drop procedure if exists bug11529|
+create procedure bug11529()
+begin
+declare c cursor for select id, data from t1 where data in (10,13);
+open c;
+begin
+declare vid char(16);
+declare vdata int;
+declare exit handler for not found begin end;
+while true do
+fetch c into vid, vdata;
+end while;
+end;
+close c;
+end|
+insert into t1 values
+('Name1', 10),
+('Name2', 11),
+('Name3', 12),
+('Name4', 13),
+('Name5', 14)|
+call bug11529()|
+call bug11529()|
+delete from t1|
+drop procedure bug11529|
drop table t1,t2;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index e7ee4b134ba..314ed58b5a9 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -3912,6 +3912,42 @@ drop procedure bug10136|
drop table t3|
#
+# BUG#11529: crash server after use stored procedure
+#
+--disable_warnings
+drop procedure if exists bug11529|
+--enable_warnings
+create procedure bug11529()
+begin
+ declare c cursor for select id, data from t1 where data in (10,13);
+
+ open c;
+ begin
+ declare vid char(16);
+ declare vdata int;
+ declare exit handler for not found begin end;
+
+ while true do
+ fetch c into vid, vdata;
+ end while;
+ end;
+ close c;
+end|
+
+insert into t1 values
+ ('Name1', 10),
+ ('Name2', 11),
+ ('Name3', 12),
+ ('Name4', 13),
+ ('Name5', 14)|
+
+call bug11529()|
+call bug11529()|
+delete from t1|
+drop procedure bug11529|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
@@ -3921,7 +3957,7 @@ drop table t3|
# Add bugs above this line. Use existing tables t1 and t2 when
-# practical, or create table t3, t3 etc temporarily (and drop them).
+# practical, or create table t3, t4 etc temporarily (and drop them).
delimiter ;|
drop table t1,t2;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index e4dc64c993d..b586546bcfe 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1935,7 +1935,7 @@ int
sp_instr_cpush::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_cpush::execute");
- thd->spcont->push_cursor(&m_lex_keeper);
+ thd->spcont->push_cursor(&m_lex_keeper, this);
*nextp= m_ip+1;
DBUG_RETURN(0);
}
@@ -1994,7 +1994,19 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
}
else
{
+ Query_arena *old_arena= thd->current_arena;
+
+ /*
+ Get the Query_arena from the cpush instruction, which contains
+ the free_list of the query, so new items (if any) are stored in
+ the right free_list, and we can cleanup after each open.
+ */
+ thd->current_arena= c->get_instr();
res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this);
+ /* Cleanup the query's items */
+ if (thd->current_arena->free_list)
+ cleanup_items(thd->current_arena->free_list);
+ thd->current_arena= old_arena;
/*
Work around the fact that errors in selects are not returned properly
(but instead converted into a warning), so if a condition handler
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index aacb9254753..d0817e43790 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -148,9 +148,9 @@ sp_rcontext::restore_variables(uint fp)
}
void
-sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper)
+sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
{
- m_cstack[m_ccount++]= new sp_cursor(lex_keeper);
+ m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i);
}
void
@@ -169,8 +169,9 @@ sp_rcontext::pop_cursors(uint count)
*
*/
-sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper)
- :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL)
+sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
+ :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL),
+ m_i(i)
{
/*
currsor can't be stored in QC, so we should prevent opening QC for
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index b188805435f..856beb13f6d 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -26,6 +26,7 @@ struct sp_cond_type;
class sp_cursor;
struct sp_pvar;
class sp_lex_keeper;
+class sp_instr_cpush;
#define SP_HANDLER_NONE 0
#define SP_HANDLER_EXIT 1
@@ -161,7 +162,7 @@ class sp_rcontext : public Sql_alloc
restore_variables(uint fp);
void
- push_cursor(sp_lex_keeper *lex_keeper);
+ push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
void
pop_cursors(uint count);
@@ -203,7 +204,7 @@ class sp_cursor : public Sql_alloc
{
public:
- sp_cursor(sp_lex_keeper *lex_keeper);
+ sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
virtual ~sp_cursor()
{
@@ -229,6 +230,12 @@ public:
int
fetch(THD *, List<struct sp_pvar> *vars);
+ inline sp_instr_cpush *
+ get_instr()
+ {
+ return m_i;
+ }
+
private:
MEM_ROOT m_mem_root; // My own mem_root
@@ -238,6 +245,7 @@ private:
my_bool m_nseof; // Original no_send_eof
Protocol *m_oprot; // Original protcol
MYSQL_ROWS *m_current_row;
+ sp_instr_cpush *m_i; // My push instruction
void
destroy();