diff options
-rw-r--r-- | mysql-test/r/sp-code.result | 109 | ||||
-rw-r--r-- | mysql-test/t/sp-code.test | 77 | ||||
-rw-r--r-- | sql/sp_head.cc | 6 | ||||
-rw-r--r-- | sql/sp_head.h | 5 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 76 | ||||
-rw-r--r-- | sql/sp_rcontext.h | 40 |
6 files changed, 276 insertions, 37 deletions
diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index 018173e723d..ca5c5b42102 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -733,6 +733,115 @@ optimizer: keep hreturn drop table t1; drop procedure proc_26977_broken; drop procedure proc_26977_works; +drop procedure if exists proc_33618_h; +drop procedure if exists proc_33618_c; +create procedure proc_33618_h(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare exit handler for 1062 begin end; +fetch cur1 into vb; +if (last_row = 1) then +## should generate a hpop instruction here +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +create procedure proc_33618_c(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare cur2 cursor for select `b` from t_33618; +fetch cur1 into vb; +if (last_row = 1) then +## should generate a cpop instruction here +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +show procedure code proc_33618_h; +Pos Instruction +0 set count1@1 _latin1'0' +1 set vb@2 NULL +2 set last_row@3 NULL +3 jump_if_not 24(24) (num@0 >= 1) +4 set num@0 (num@0 - 1) +5 cpush cur1@0 +6 hpush_jump 9 4 CONTINUE +7 set last_row@3 1 +8 hreturn 4 +9 set last_row@3 0 +10 copen cur1@0 +11 hpush_jump 13 4 EXIT +12 hreturn 0 17 +13 cfetch cur1@0 vb@2 +14 jump_if_not 17(17) (last_row@3 = 1) +15 hpop 1 +16 jump 19 +17 hpop 1 +18 jump_if_not 11(19) (last_row@3 = 1) +19 cclose cur1@0 +20 hpop 1 +21 cpop 1 +22 jump 3 +show procedure code proc_33618_c; +Pos Instruction +0 set count1@1 _latin1'0' +1 set vb@2 NULL +2 set last_row@3 NULL +3 jump_if_not 23(23) (num@0 >= 1) +4 set num@0 (num@0 - 1) +5 cpush cur1@0 +6 hpush_jump 9 4 CONTINUE +7 set last_row@3 1 +8 hreturn 4 +9 set last_row@3 0 +10 copen cur1@0 +11 cpush cur2@1 +12 cfetch cur1@0 vb@2 +13 jump_if_not 16(16) (last_row@3 = 1) +14 cpop 1 +15 jump 18 +16 cpop 1 +17 jump_if_not 11(18) (last_row@3 = 1) +18 cclose cur1@0 +19 hpop 1 +20 cpop 1 +21 jump 3 +drop procedure proc_33618_h; +drop procedure proc_33618_c; End of 5.0 tests. CREATE PROCEDURE p1() BEGIN diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test index 66d5323d2e2..84f0201c808 100644 --- a/mysql-test/t/sp-code.test +++ b/mysql-test/t/sp-code.test @@ -520,6 +520,83 @@ drop table t1; drop procedure proc_26977_broken; drop procedure proc_26977_works; +# +# Bug#33618 Crash in sp_rcontext +# + +--disable_warnings +drop procedure if exists proc_33618_h; +drop procedure if exists proc_33618_c; +--enable_warnings + +delimiter //; + +create procedure proc_33618_h(num int) +begin + declare count1 int default '0'; + declare vb varchar(30); + declare last_row int; + + while(num>=1) do + set num=num-1; + begin + declare cur1 cursor for select `a` from t_33618; + declare continue handler for not found set last_row = 1; + set last_row:=0; + open cur1; + rep1: + repeat + begin + declare exit handler for 1062 begin end; + fetch cur1 into vb; + if (last_row = 1) then + ## should generate a hpop instruction here + leave rep1; + end if; + end; + until last_row=1 + end repeat; + close cur1; + end; + end while; +end// + +create procedure proc_33618_c(num int) +begin + declare count1 int default '0'; + declare vb varchar(30); + declare last_row int; + + while(num>=1) do + set num=num-1; + begin + declare cur1 cursor for select `a` from t_33618; + declare continue handler for not found set last_row = 1; + set last_row:=0; + open cur1; + rep1: + repeat + begin + declare cur2 cursor for select `b` from t_33618; + fetch cur1 into vb; + if (last_row = 1) then + ## should generate a cpop instruction here + leave rep1; + end if; + end; + until last_row=1 + end repeat; + close cur1; + end; + end while; +end// +delimiter ;// + +show procedure code proc_33618_h; +show procedure code proc_33618_c; + +drop procedure proc_33618_h; +drop procedure proc_33618_c; --echo End of 5.0 tests. diff --git a/sql/sp_head.cc b/sql/sp_head.cc index bae85d8c092..74f5bf55828 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2074,11 +2074,17 @@ sp_head::backpatch(sp_label_t *lab) uint dest= instructions(); List_iterator_fast<bp_t> li(m_backpatch); + DBUG_ENTER("sp_head::backpatch"); while ((bp= li++)) { if (bp->lab == lab) + { + DBUG_PRINT("info", ("backpatch: (m_ip %d, label 0x%lx <%s>) to dest %d", + bp->instr->m_ip, (ulong) lab, lab->name, dest)); bp->instr->backpatch(dest, lab->ctx); + } } + DBUG_VOID_RETURN; } /* diff --git a/sql/sp_head.h b/sql/sp_head.h index 86a77a434ff..288584ff200 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -877,8 +877,9 @@ public: virtual void backpatch(uint dest, sp_pcontext *dst_ctx) { - if (m_dest == 0) // Don't reset - m_dest= dest; + /* Calling backpatch twice is a logic flaw in jump resolution. */ + DBUG_ASSERT(m_dest == 0); + m_dest= dest; } /* diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 8395648689b..9b237b3e7cc 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -314,17 +314,91 @@ sp_rcontext::handle_error(uint sql_errno, void sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) { + DBUG_ENTER("sp_rcontext::push_cursor"); + DBUG_ASSERT(m_ccount < m_root_parsing_ctx->max_cursor_index()); m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i); + DBUG_PRINT("info", ("m_ccount: %d", m_ccount)); + DBUG_VOID_RETURN; } - void sp_rcontext::pop_cursors(uint count) { + DBUG_ENTER("sp_rcontext::pop_cursors"); + DBUG_ASSERT(m_ccount >= count); while (count--) { delete m_cstack[--m_ccount]; } + DBUG_PRINT("info", ("m_ccount: %d", m_ccount)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type, uint f) +{ + DBUG_ENTER("sp_rcontext::push_handler"); + DBUG_ASSERT(m_hcount < m_root_parsing_ctx->max_handler_index()); + + m_handler[m_hcount].cond= cond; + m_handler[m_hcount].handler= h; + m_handler[m_hcount].type= type; + m_handler[m_hcount].foffset= f; + m_hcount+= 1; + + DBUG_PRINT("info", ("m_hcount: %d", m_hcount)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::pop_handlers(uint count) +{ + DBUG_ENTER("sp_rcontext::pop_handlers"); + DBUG_ASSERT(m_hcount >= count); + m_hcount-= count; + DBUG_PRINT("info", ("m_hcount: %d", m_hcount)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::push_hstack(uint h) +{ + DBUG_ENTER("sp_rcontext::push_hstack"); + DBUG_ASSERT(m_hsp < m_root_parsing_ctx->max_handler_index()); + m_hstack[m_hsp++]= h; + DBUG_PRINT("info", ("m_hsp: %d", m_hsp)); + DBUG_VOID_RETURN; +} + +uint +sp_rcontext::pop_hstack() +{ + uint handler; + DBUG_ENTER("sp_rcontext::pop_hstack"); + DBUG_ASSERT(m_hsp); + handler= m_hstack[--m_hsp]; + DBUG_PRINT("info", ("m_hsp: %d", m_hsp)); + DBUG_RETURN(handler); +} + +void +sp_rcontext::enter_handler(int hid) +{ + DBUG_ENTER("sp_rcontext::enter_handler"); + DBUG_ASSERT(m_ihsp < m_root_parsing_ctx->max_handler_index()); + m_in_handler[m_ihsp++]= hid; + DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::exit_handler() +{ + DBUG_ENTER("sp_rcontext::exit_handler"); + DBUG_ASSERT(m_ihsp); + m_ihsp-= 1; + DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp)); + DBUG_VOID_RETURN; } diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 43102cfeeb2..368a017da21 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -107,21 +107,9 @@ class sp_rcontext : public Sql_alloc return m_return_value_set; } - inline void - push_handler(struct sp_cond_type *cond, uint h, int type, uint f) - { - m_handler[m_hcount].cond= cond; - m_handler[m_hcount].handler= h; - m_handler[m_hcount].type= type; - m_handler[m_hcount].foffset= f; - m_hcount+= 1; - } + void push_handler(struct sp_cond_type *cond, uint h, int type, uint f); - inline void - pop_handlers(uint count) - { - m_hcount-= count; - } + void pop_handlers(uint count); // Returns 1 if a handler was found, 0 otherwise. bool @@ -158,29 +146,13 @@ class sp_rcontext : public Sql_alloc m_hfound= -1; } - inline void - push_hstack(uint h) - { - m_hstack[m_hsp++]= h; - } + void push_hstack(uint h); - inline uint - pop_hstack() - { - return m_hstack[--m_hsp]; - } + uint pop_hstack(); - inline void - enter_handler(int hid) - { - m_in_handler[m_ihsp++]= hid; - } + void enter_handler(int hid); - inline void - exit_handler() - { - m_ihsp-= 1; - } + void exit_handler(); void push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); |