Skip to content

Commit c3ad0ca

Browse files
author
malff@lambda.hsd1.co.comcast.net.
committed
Bug#33618 (Crash in sp_rcontext)
Bug 33983 (Stored Procedures: wrong end <label> syntax is accepted) The server used to crash when REPEAT or another control instruction was used in conjunction with labels and a LEAVE instruction. The crash was caused by a missing "pop" of handlers or cursors in the code representing the stored program. When executing the code in a loop, this missing "pop" would result in a stack overflow, corrupting memory. Code generation has been fixed to produce the missing h_pop/c_pop instructions. Also, the logic checking that labels at the beginning and the end of a statement are matched was incorrect, causing Bug 33983. End labels, when used, must match the label used at the beginning of a block.
1 parent 4bb5035 commit c3ad0ca

11 files changed

+549
-50
lines changed

mysql-test/r/sp-code.result

+109
Original file line numberDiff line numberDiff line change
@@ -733,4 +733,113 @@ optimizer: keep hreturn
733733
drop table t1;
734734
drop procedure proc_26977_broken;
735735
drop procedure proc_26977_works;
736+
drop procedure if exists proc_33618_h;
737+
drop procedure if exists proc_33618_c;
738+
create procedure proc_33618_h(num int)
739+
begin
740+
declare count1 int default '0';
741+
declare vb varchar(30);
742+
declare last_row int;
743+
while(num>=1) do
744+
set num=num-1;
745+
begin
746+
declare cur1 cursor for select `a` from t_33618;
747+
declare continue handler for not found set last_row = 1;
748+
set last_row:=0;
749+
open cur1;
750+
rep1:
751+
repeat
752+
begin
753+
declare exit handler for 1062 begin end;
754+
fetch cur1 into vb;
755+
if (last_row = 1) then
756+
## should generate a hpop instruction here
757+
leave rep1;
758+
end if;
759+
end;
760+
until last_row=1
761+
end repeat;
762+
close cur1;
763+
end;
764+
end while;
765+
end//
766+
create procedure proc_33618_c(num int)
767+
begin
768+
declare count1 int default '0';
769+
declare vb varchar(30);
770+
declare last_row int;
771+
while(num>=1) do
772+
set num=num-1;
773+
begin
774+
declare cur1 cursor for select `a` from t_33618;
775+
declare continue handler for not found set last_row = 1;
776+
set last_row:=0;
777+
open cur1;
778+
rep1:
779+
repeat
780+
begin
781+
declare cur2 cursor for select `b` from t_33618;
782+
fetch cur1 into vb;
783+
if (last_row = 1) then
784+
## should generate a cpop instruction here
785+
leave rep1;
786+
end if;
787+
end;
788+
until last_row=1
789+
end repeat;
790+
close cur1;
791+
end;
792+
end while;
793+
end//
794+
show procedure code proc_33618_h;
795+
Pos Instruction
796+
0 set count1@1 _latin1'0'
797+
1 set vb@2 NULL
798+
2 set last_row@3 NULL
799+
3 jump_if_not 24(24) (num@0 >= 1)
800+
4 set num@0 (num@0 - 1)
801+
5 cpush cur1@0
802+
6 hpush_jump 9 4 CONTINUE
803+
7 set last_row@3 1
804+
8 hreturn 4
805+
9 set last_row@3 0
806+
10 copen cur1@0
807+
11 hpush_jump 13 4 EXIT
808+
12 hreturn 0 17
809+
13 cfetch cur1@0 vb@2
810+
14 jump_if_not 17(17) (last_row@3 = 1)
811+
15 hpop 1
812+
16 jump 19
813+
17 hpop 1
814+
18 jump_if_not 11(19) (last_row@3 = 1)
815+
19 cclose cur1@0
816+
20 hpop 1
817+
21 cpop 1
818+
22 jump 3
819+
show procedure code proc_33618_c;
820+
Pos Instruction
821+
0 set count1@1 _latin1'0'
822+
1 set vb@2 NULL
823+
2 set last_row@3 NULL
824+
3 jump_if_not 23(23) (num@0 >= 1)
825+
4 set num@0 (num@0 - 1)
826+
5 cpush cur1@0
827+
6 hpush_jump 9 4 CONTINUE
828+
7 set last_row@3 1
829+
8 hreturn 4
830+
9 set last_row@3 0
831+
10 copen cur1@0
832+
11 cpush cur2@1
833+
12 cfetch cur1@0 vb@2
834+
13 jump_if_not 16(16) (last_row@3 = 1)
835+
14 cpop 1
836+
15 jump 18
837+
16 cpop 1
838+
17 jump_if_not 11(18) (last_row@3 = 1)
839+
18 cclose cur1@0
840+
19 hpop 1
841+
20 cpop 1
842+
21 jump 3
843+
drop procedure proc_33618_h;
844+
drop procedure proc_33618_c;
736845
End of 5.0 tests.

mysql-test/r/sp-error.result

+48
Original file line numberDiff line numberDiff line change
@@ -1465,3 +1465,51 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
14651465
SELECT ..inexistent();
14661466
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.inexistent()' at line 1
14671467
USE test;
1468+
drop procedure if exists proc_33983_a;
1469+
drop procedure if exists proc_33983_b;
1470+
drop procedure if exists proc_33983_c;
1471+
drop procedure if exists proc_33983_d;
1472+
create procedure proc_33983_a()
1473+
begin
1474+
label1:
1475+
begin
1476+
label2:
1477+
begin
1478+
select 1;
1479+
end label1;
1480+
end;
1481+
end|
1482+
ERROR 42000: End-label label1 without match
1483+
create procedure proc_33983_b()
1484+
begin
1485+
label1:
1486+
repeat
1487+
label2:
1488+
repeat
1489+
select 1;
1490+
until FALSE end repeat label1;
1491+
until FALSE end repeat;
1492+
end|
1493+
ERROR 42000: End-label label1 without match
1494+
create procedure proc_33983_c()
1495+
begin
1496+
label1:
1497+
while TRUE do
1498+
label2:
1499+
while TRUE do
1500+
select 1;
1501+
end while label1;
1502+
end while;
1503+
end|
1504+
ERROR 42000: End-label label1 without match
1505+
create procedure proc_33983_d()
1506+
begin
1507+
label1:
1508+
loop
1509+
label2:
1510+
loop
1511+
select 1;
1512+
end loop label1;
1513+
end loop;
1514+
end|
1515+
ERROR 42000: End-label label1 without match

mysql-test/r/sp.result

+35
Original file line numberDiff line numberDiff line change
@@ -6578,6 +6578,41 @@ DROP PROCEDURE db28318_a.t1;
65786578
DROP PROCEDURE db28318_b.t2;
65796579
DROP DATABASE db28318_a;
65806580
DROP DATABASE db28318_b;
6581+
use test;
6582+
drop table if exists t_33618;
6583+
drop procedure if exists proc_33618;
6584+
create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam;
6585+
insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2');
6586+
create procedure proc_33618(num int)
6587+
begin
6588+
declare count1 int default '0';
6589+
declare vb varchar(30);
6590+
declare last_row int;
6591+
while(num>=1) do
6592+
set num=num-1;
6593+
begin
6594+
declare cur1 cursor for select `a` from t_33618;
6595+
declare continue handler for not found set last_row = 1;
6596+
set last_row:=0;
6597+
open cur1;
6598+
rep1:
6599+
repeat
6600+
begin
6601+
declare exit handler for 1062 begin end;
6602+
fetch cur1 into vb;
6603+
if (last_row = 1) then
6604+
leave rep1;
6605+
end if;
6606+
end;
6607+
until last_row=1
6608+
end repeat;
6609+
close cur1;
6610+
end;
6611+
end while;
6612+
end//
6613+
call proc_33618(20);
6614+
drop table t_33618;
6615+
drop procedure proc_33618;
65816616
# ------------------------------------------------------------------
65826617
# -- End of 5.0 tests
65836618
# ------------------------------------------------------------------

mysql-test/t/sp-code.test

+77
Original file line numberDiff line numberDiff line change
@@ -520,5 +520,82 @@ drop table t1;
520520
drop procedure proc_26977_broken;
521521
drop procedure proc_26977_works;
522522

523+
#
524+
# Bug#33618 Crash in sp_rcontext
525+
#
526+
527+
--disable_warnings
528+
drop procedure if exists proc_33618_h;
529+
drop procedure if exists proc_33618_c;
530+
--enable_warnings
531+
532+
delimiter //;
533+
534+
create procedure proc_33618_h(num int)
535+
begin
536+
declare count1 int default '0';
537+
declare vb varchar(30);
538+
declare last_row int;
539+
540+
while(num>=1) do
541+
set num=num-1;
542+
begin
543+
declare cur1 cursor for select `a` from t_33618;
544+
declare continue handler for not found set last_row = 1;
545+
set last_row:=0;
546+
open cur1;
547+
rep1:
548+
repeat
549+
begin
550+
declare exit handler for 1062 begin end;
551+
fetch cur1 into vb;
552+
if (last_row = 1) then
553+
## should generate a hpop instruction here
554+
leave rep1;
555+
end if;
556+
end;
557+
until last_row=1
558+
end repeat;
559+
close cur1;
560+
end;
561+
end while;
562+
end//
563+
564+
create procedure proc_33618_c(num int)
565+
begin
566+
declare count1 int default '0';
567+
declare vb varchar(30);
568+
declare last_row int;
569+
570+
while(num>=1) do
571+
set num=num-1;
572+
begin
573+
declare cur1 cursor for select `a` from t_33618;
574+
declare continue handler for not found set last_row = 1;
575+
set last_row:=0;
576+
open cur1;
577+
rep1:
578+
repeat
579+
begin
580+
declare cur2 cursor for select `b` from t_33618;
581+
fetch cur1 into vb;
582+
if (last_row = 1) then
583+
## should generate a cpop instruction here
584+
leave rep1;
585+
end if;
586+
end;
587+
until last_row=1
588+
end repeat;
589+
close cur1;
590+
end;
591+
end while;
592+
end//
593+
delimiter ;//
594+
595+
show procedure code proc_33618_h;
596+
show procedure code proc_33618_c;
597+
598+
drop procedure proc_33618_h;
599+
drop procedure proc_33618_c;
523600

524601
--echo End of 5.0 tests.

mysql-test/t/sp-error.test

+63
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,69 @@ SELECT .inexistent();
21122112
SELECT ..inexistent();
21132113
USE test;
21142114

2115+
#
2116+
# Bug#33983 (Stored Procedures: wrong end <label> syntax is accepted)
2117+
#
2118+
2119+
--disable_warnings
2120+
drop procedure if exists proc_33983_a;
2121+
drop procedure if exists proc_33983_b;
2122+
drop procedure if exists proc_33983_c;
2123+
drop procedure if exists proc_33983_d;
2124+
--enable_warnings
2125+
2126+
delimiter |;
2127+
2128+
--error ER_SP_LABEL_MISMATCH
2129+
create procedure proc_33983_a()
2130+
begin
2131+
label1:
2132+
begin
2133+
label2:
2134+
begin
2135+
select 1;
2136+
end label1;
2137+
end;
2138+
end|
2139+
2140+
--error ER_SP_LABEL_MISMATCH
2141+
create procedure proc_33983_b()
2142+
begin
2143+
label1:
2144+
repeat
2145+
label2:
2146+
repeat
2147+
select 1;
2148+
until FALSE end repeat label1;
2149+
until FALSE end repeat;
2150+
end|
2151+
2152+
--error ER_SP_LABEL_MISMATCH
2153+
create procedure proc_33983_c()
2154+
begin
2155+
label1:
2156+
while TRUE do
2157+
label2:
2158+
while TRUE do
2159+
select 1;
2160+
end while label1;
2161+
end while;
2162+
end|
2163+
2164+
--error ER_SP_LABEL_MISMATCH
2165+
create procedure proc_33983_d()
2166+
begin
2167+
label1:
2168+
loop
2169+
label2:
2170+
loop
2171+
select 1;
2172+
end loop label1;
2173+
end loop;
2174+
end|
2175+
2176+
delimiter ;|
2177+
21152178
#
21162179
# BUG#NNNN: New bug synopsis
21172180
#

0 commit comments

Comments
 (0)