mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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. mysql-test/r/sp-code.result: Bug#33618 (Crash in sp_rcontext) mysql-test/r/sp-error.result: Bug 33983 (Stored Procedures: wrong end <label> syntax is accepted) mysql-test/r/sp.result: Bug#33618 (Crash in sp_rcontext) mysql-test/t/sp-code.test: Bug#33618 (Crash in sp_rcontext) mysql-test/t/sp-error.test: Bug 33983 (Stored Procedures: wrong end <label> syntax is accepted) mysql-test/t/sp.test: Bug#33618 (Crash in sp_rcontext) sql/sp_head.cc: Bug#33618 (Crash in sp_rcontext) sql/sp_head.h: Bug#33618 (Crash in sp_rcontext) sql/sp_rcontext.cc: Bug#33618 (Crash in sp_rcontext) sql/sp_rcontext.h: Bug#33618 (Crash in sp_rcontext) sql/sql_yacc.yy: Bug#33618 (Crash in sp_rcontext)
This commit is contained in:
@ -733,4 +733,113 @@ 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.
|
||||
|
@ -1465,3 +1465,51 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
|
||||
SELECT ..inexistent();
|
||||
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
|
||||
USE test;
|
||||
drop procedure if exists proc_33983_a;
|
||||
drop procedure if exists proc_33983_b;
|
||||
drop procedure if exists proc_33983_c;
|
||||
drop procedure if exists proc_33983_d;
|
||||
create procedure proc_33983_a()
|
||||
begin
|
||||
label1:
|
||||
begin
|
||||
label2:
|
||||
begin
|
||||
select 1;
|
||||
end label1;
|
||||
end;
|
||||
end|
|
||||
ERROR 42000: End-label label1 without match
|
||||
create procedure proc_33983_b()
|
||||
begin
|
||||
label1:
|
||||
repeat
|
||||
label2:
|
||||
repeat
|
||||
select 1;
|
||||
until FALSE end repeat label1;
|
||||
until FALSE end repeat;
|
||||
end|
|
||||
ERROR 42000: End-label label1 without match
|
||||
create procedure proc_33983_c()
|
||||
begin
|
||||
label1:
|
||||
while TRUE do
|
||||
label2:
|
||||
while TRUE do
|
||||
select 1;
|
||||
end while label1;
|
||||
end while;
|
||||
end|
|
||||
ERROR 42000: End-label label1 without match
|
||||
create procedure proc_33983_d()
|
||||
begin
|
||||
label1:
|
||||
loop
|
||||
label2:
|
||||
loop
|
||||
select 1;
|
||||
end loop label1;
|
||||
end loop;
|
||||
end|
|
||||
ERROR 42000: End-label label1 without match
|
||||
|
@ -6578,6 +6578,41 @@ DROP PROCEDURE db28318_a.t1;
|
||||
DROP PROCEDURE db28318_b.t2;
|
||||
DROP DATABASE db28318_a;
|
||||
DROP DATABASE db28318_b;
|
||||
use test;
|
||||
drop table if exists t_33618;
|
||||
drop procedure if exists proc_33618;
|
||||
create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam;
|
||||
insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2');
|
||||
create procedure proc_33618(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
|
||||
leave rep1;
|
||||
end if;
|
||||
end;
|
||||
until last_row=1
|
||||
end repeat;
|
||||
close cur1;
|
||||
end;
|
||||
end while;
|
||||
end//
|
||||
call proc_33618(20);
|
||||
drop table t_33618;
|
||||
drop procedure proc_33618;
|
||||
# ------------------------------------------------------------------
|
||||
# -- End of 5.0 tests
|
||||
# ------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user