diff options
-rw-r--r-- | mysql-test/r/sp.result | 25 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 38 | ||||
-rw-r--r-- | sql/sp_head.cc | 14 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 9 | ||||
-rw-r--r-- | sql/sp_rcontext.h | 12 |
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(); |