Commit a95bb38a authored by unknown's avatar unknown

Fixed BUG#11529: crash server after use stored procedure

Make sure to cleanup the items for a cursor query after each open, otherwise
it's done too late, after the run-time mem_root is freed.


mysql-test/r/sp.result:
  New test case for BUG#11529.
mysql-test/t/sp.test:
  New test case for BUG#11529.
sql/sp_head.cc:
  Add a back pointer from a sp_cursor to its cpush instruction, and use it to set
  the arena and cleanup the items for the cursor's query when opening it.
sql/sp_rcontext.cc:
  Store pointer in sp_cursor to its cpush instruction.
sql/sp_rcontext.h:
  Store pointer in sp_cursor to its cpush instruction.
parent ec9ac3fe
...@@ -3224,4 +3224,29 @@ bbbbb 2 ...@@ -3224,4 +3224,29 @@ bbbbb 2
ccccc 3 ccccc 3
drop procedure bug10136| drop procedure bug10136|
drop table t3| 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; drop table t1,t2;
...@@ -3911,6 +3911,42 @@ call bug10136()| ...@@ -3911,6 +3911,42 @@ call bug10136()|
drop procedure bug10136| drop procedure bug10136|
drop table t3| 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 # BUG#NNNN: New bug synopsis
# #
...@@ -3921,7 +3957,7 @@ drop table t3| ...@@ -3921,7 +3957,7 @@ drop table t3|
# Add bugs above this line. Use existing tables t1 and t2 when # 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 ;| delimiter ;|
drop table t1,t2; drop table t1,t2;
...@@ -1935,7 +1935,7 @@ int ...@@ -1935,7 +1935,7 @@ int
sp_instr_cpush::execute(THD *thd, uint *nextp) sp_instr_cpush::execute(THD *thd, uint *nextp)
{ {
DBUG_ENTER("sp_instr_cpush::execute"); 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; *nextp= m_ip+1;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1994,7 +1994,19 @@ sp_instr_copen::execute(THD *thd, uint *nextp) ...@@ -1994,7 +1994,19 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
} }
else 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); 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 Work around the fact that errors in selects are not returned properly
(but instead converted into a warning), so if a condition handler (but instead converted into a warning), so if a condition handler
......
...@@ -148,9 +148,9 @@ sp_rcontext::restore_variables(uint fp) ...@@ -148,9 +148,9 @@ sp_rcontext::restore_variables(uint fp)
} }
void 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 void
...@@ -169,8 +169,9 @@ sp_rcontext::pop_cursors(uint count) ...@@ -169,8 +169,9 @@ sp_rcontext::pop_cursors(uint count)
* *
*/ */
sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper) 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_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 currsor can't be stored in QC, so we should prevent opening QC for
......
...@@ -26,6 +26,7 @@ struct sp_cond_type; ...@@ -26,6 +26,7 @@ struct sp_cond_type;
class sp_cursor; class sp_cursor;
struct sp_pvar; struct sp_pvar;
class sp_lex_keeper; class sp_lex_keeper;
class sp_instr_cpush;
#define SP_HANDLER_NONE 0 #define SP_HANDLER_NONE 0
#define SP_HANDLER_EXIT 1 #define SP_HANDLER_EXIT 1
...@@ -161,7 +162,7 @@ class sp_rcontext : public Sql_alloc ...@@ -161,7 +162,7 @@ class sp_rcontext : public Sql_alloc
restore_variables(uint fp); restore_variables(uint fp);
void void
push_cursor(sp_lex_keeper *lex_keeper); push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
void void
pop_cursors(uint count); pop_cursors(uint count);
...@@ -203,7 +204,7 @@ class sp_cursor : public Sql_alloc ...@@ -203,7 +204,7 @@ class sp_cursor : public Sql_alloc
{ {
public: public:
sp_cursor(sp_lex_keeper *lex_keeper); sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
virtual ~sp_cursor() virtual ~sp_cursor()
{ {
...@@ -229,6 +230,12 @@ public: ...@@ -229,6 +230,12 @@ public:
int int
fetch(THD *, List<struct sp_pvar> *vars); fetch(THD *, List<struct sp_pvar> *vars);
inline sp_instr_cpush *
get_instr()
{
return m_i;
}
private: private:
MEM_ROOT m_mem_root; // My own mem_root MEM_ROOT m_mem_root; // My own mem_root
...@@ -238,6 +245,7 @@ private: ...@@ -238,6 +245,7 @@ private:
my_bool m_nseof; // Original no_send_eof my_bool m_nseof; // Original no_send_eof
Protocol *m_oprot; // Original protcol Protocol *m_oprot; // Original protcol
MYSQL_ROWS *m_current_row; MYSQL_ROWS *m_current_row;
sp_instr_cpush *m_i; // My push instruction
void void
destroy(); destroy();
......
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