summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordlenev@brandersnatch.localdomain <>2005-07-01 13:01:46 +0400
committerdlenev@brandersnatch.localdomain <>2005-07-01 13:01:46 +0400
commit56ff9f16535d2cb94f6a983b40ed6b6f16e5b370 (patch)
treef780b41399823750ea4737fc932dfa4c34d0319c
parentf2e358d9dbde3eaf5b62d047b720c078eebbeb41 (diff)
downloadmariadb-git-56ff9f16535d2cb94f6a983b40ed6b6f16e5b370.tar.gz
"Fix" for bug #11394 "Recursion in SP crash server" and bug #11600
"Stored procedures: crash with function calling itself". Disallow recursive stored routines until we either make Item's and LEX reentrant safe or will use spearate sp_head instances (and thus separate LEX objects and Item trees) for each routine invocation.
-rw-r--r--mysql-test/r/sp-error.result40
-rw-r--r--mysql-test/r/sp.result68
-rw-r--r--mysql-test/t/sp-error.test55
-rw-r--r--mysql-test/t/sp.test136
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sp_head.cc26
-rw-r--r--sql/sp_head.h3
7 files changed, 195 insertions, 135 deletions
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index b6ba737a8ba..814abe4f56d 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -686,3 +686,43 @@ ERROR 0A000: EXECUTE is not allowed in stored procedures
create function f() returns int begin execute stmt;
ERROR 0A000: EXECUTE is not allowed in stored procedures
deallocate prepare stmt;
+drop function if exists bug11394|
+drop function if exists bug11394_1|
+drop function if exists bug11394_2|
+drop procedure if exists bug11394|
+create function bug11394(i int) returns int
+begin
+if i <= 0 then
+return 0;
+else
+return (i in (100, 200, bug11394(i-1), 400));
+end if;
+end|
+select bug11394(2)|
+ERROR HY000: Recursive stored routines are not allowed.
+drop function bug11394|
+create function bug11394_1(i int) returns int
+begin
+if i <= 0 then
+return 0;
+else
+return (select bug11394_1(i-1));
+end if;
+end|
+select bug11394_1(2)|
+ERROR HY000: Recursive stored routines are not allowed.
+drop function bug11394_1|
+create function bug11394_2(i int) returns int return i|
+select bug11394_2(bug11394_2(10))|
+bug11394_2(bug11394_2(10))
+10
+drop function bug11394_2|
+create procedure bug11394(i int, j int)
+begin
+if i > 0 then
+call bug11394(i - 1,(select 1));
+end if;
+end|
+call bug11394(2, 1)|
+ERROR HY000: Recursive stored routines are not allowed.
+drop procedure bug11394|
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index ed858ba27ee..2840e82829c 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1396,60 +1396,6 @@ drop procedure opp|
drop procedure ip|
show procedure status like '%p%'|
Db Name Type Definer Modified Created Security_type Comment
-drop table if exists fib|
-create table fib ( f bigint unsigned not null )|
-drop procedure if exists fib|
-create procedure fib(n int unsigned)
-begin
-if n > 1 then
-begin
-declare x, y bigint unsigned;
-declare c cursor for select f from fib order by f desc limit 2;
-open c;
-fetch c into y;
-fetch c into x;
-close c;
-insert into fib values (x+y);
-call fib(n-1);
-end;
-end if;
-end|
-insert into fib values (0), (1)|
-call fib(3)|
-select * from fib order by f asc|
-f
-0
-1
-1
-2
-delete from fib|
-insert into fib values (0), (1)|
-call fib(20)|
-select * from fib order by f asc|
-f
-0
-1
-1
-2
-3
-5
-8
-13
-21
-34
-55
-89
-144
-233
-377
-610
-987
-1597
-2584
-4181
-6765
-drop table fib|
-drop procedure fib|
drop procedure if exists bar|
create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker
@@ -2506,20 +2452,6 @@ s1
1
drop procedure bug4905|
drop table t3|
-drop function if exists bug6022|
-drop function if exists bug6022|
-create function bug6022(x int) returns int
-begin
-if x < 0 then
-return 0;
-else
-return bug6022(x-1);
-end if;
-end|
-select bug6022(5)|
-bug6022(5)
-0
-drop function bug6022|
drop procedure if exists bug6029|
drop procedure if exists bug6029|
create procedure bug6029()
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index faf6d8b4de3..ea49aff8bbe 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -986,3 +986,58 @@ create procedure p() execute stmt;
create function f() returns int begin execute stmt;
deallocate prepare stmt;
+#
+# Bug #11394 "Recursion in SP crash server" and bug #11600 "Stored
+# procedures: crash with function calling itself".
+# We have to disable recursion since in many cases LEX and many
+# Item's can't be used in reentrant way nowdays.
+delimiter |;
+--disable_warnings
+drop function if exists bug11394|
+drop function if exists bug11394_1|
+drop function if exists bug11394_2|
+drop procedure if exists bug11394|
+--enable_warnings
+create function bug11394(i int) returns int
+begin
+ if i <= 0 then
+ return 0;
+ else
+ return (i in (100, 200, bug11394(i-1), 400));
+ end if;
+end|
+# If we allow recursive functions without additional modifications
+# this will crash server since Item for "IN" is not reenterable.
+--error 1423
+select bug11394(2)|
+drop function bug11394|
+create function bug11394_1(i int) returns int
+begin
+ if i <= 0 then
+ return 0;
+ else
+ return (select bug11394_1(i-1));
+ end if;
+end|
+# The following statement will crash because some LEX members responsible
+# for selects cannot be used in reentrant fashion.
+--error 1423
+select bug11394_1(2)|
+drop function bug11394_1|
+# Note that the following should be allowed since it does not contains
+# recursion
+create function bug11394_2(i int) returns int return i|
+select bug11394_2(bug11394_2(10))|
+drop function bug11394_2|
+create procedure bug11394(i int, j int)
+begin
+ if i > 0 then
+ call bug11394(i - 1,(select 1));
+ end if;
+end|
+# Again if we allow recursion for stored procedures (without
+# additional efforts) the following statement will crash the server.
+--error 1423
+call bug11394(2, 1)|
+drop procedure bug11394|
+delimiter |;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index e7ee4b134ba..4d22f1d4b90 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1630,54 +1630,56 @@ show procedure status like '%p%'|
# Fibonacci, for recursion test. (Yet Another Numerical series :)
-
---disable_warnings
-drop table if exists fib|
---enable_warnings
-create table fib ( f bigint unsigned not null )|
-
-# We deliberately do it the awkward way, fetching the last two
-# values from the table, in order to exercise various statements
-# and table accesses at each turn.
---disable_warnings
-drop procedure if exists fib|
---enable_warnings
-create procedure fib(n int unsigned)
-begin
- if n > 1 then
- begin
- declare x, y bigint unsigned;
- declare c cursor for select f from fib order by f desc limit 2;
-
- open c;
- fetch c into y;
- fetch c into x;
- close c;
- insert into fib values (x+y);
- call fib(n-1);
- end;
- end if;
-end|
-
-# Minimum test: recursion of 3 levels
-
-insert into fib values (0), (1)|
-
-call fib(3)|
-
-select * from fib order by f asc|
-
-delete from fib|
-
-# Original test: 20 levels (may run into memory limits!)
-
-insert into fib values (0), (1)|
-
-call fib(20)|
-
-select * from fib order by f asc|
-drop table fib|
-drop procedure fib|
+#
+# This part of test is disabled until we implement support for
+# recursive stored procedures.
+#--disable_warnings
+#drop table if exists fib|
+#--enable_warnings
+#create table fib ( f bigint unsigned not null )|
+#
+## We deliberately do it the awkward way, fetching the last two
+## values from the table, in order to exercise various statements
+## and table accesses at each turn.
+#--disable_warnings
+#drop procedure if exists fib|
+#--enable_warnings
+#create procedure fib(n int unsigned)
+#begin
+# if n > 1 then
+# begin
+# declare x, y bigint unsigned;
+# declare c cursor for select f from fib order by f desc limit 2;
+#
+# open c;
+# fetch c into y;
+# fetch c into x;
+# close c;
+# insert into fib values (x+y);
+# call fib(n-1);
+# end;
+# end if;
+#end|
+#
+## Minimum test: recursion of 3 levels
+#
+#insert into fib values (0), (1)|
+#
+#call fib(3)|
+#
+#select * from fib order by f asc|
+#
+#delete from fib|
+#
+## Original test: 20 levels (may run into memory limits!)
+#
+#insert into fib values (0), (1)|
+#
+#call fib(20)|
+#
+#select * from fib order by f asc|
+#drop table fib|
+#drop procedure fib|
#
@@ -3011,24 +3013,26 @@ drop table t3|
#
# BUG#6022: Stored procedure shutdown problem with self-calling function.
#
---disable_warnings
-drop function if exists bug6022|
---enable_warnings
-
---disable_warnings
-drop function if exists bug6022|
---enable_warnings
-create function bug6022(x int) returns int
-begin
- if x < 0 then
- return 0;
- else
- return bug6022(x-1);
- end if;
-end|
-
-select bug6022(5)|
-drop function bug6022|
+# This part of test is disabled until we implement support for
+# recursive stored functions.
+#--disable_warnings
+#drop function if exists bug6022|
+#--enable_warnings
+#
+#--disable_warnings
+#drop function if exists bug6022|
+#--enable_warnings
+#create function bug6022(x int) returns int
+#begin
+# if x < 0 then
+# return 0;
+# else
+# return bug6022(x-1);
+# end if;
+#end|
+#
+#select bug6022(5)|
+#drop function bug6022|
#
# BUG#6029: Stored procedure specific handlers should have priority
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 7ae5130764f..8230443da48 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5358,3 +5358,5 @@ ER_STMT_HAS_NO_OPEN_CURSOR
eng "The statement (%lu) has no open cursor."
ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
eng "Explicit or implicit commit is not allowed in stored function or trigger."
+ER_SP_NO_RECURSION
+ eng "Recursive stored routines are not allowed."
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index e4dc64c993d..3d5525015c6 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -312,7 +312,8 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head()
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
m_returns_cs(NULL), m_has_return(FALSE),
- m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE)
+ m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE),
+ m_is_invoked(FALSE)
{
extern byte *
sp_table_key(const byte *ptr, uint *plen, my_bool first);
@@ -587,6 +588,28 @@ sp_head::execute(THD *thd)
DBUG_RETURN(-1);
}
+ if (m_is_invoked)
+ {
+ /*
+ We have to disable recursion for stored routines since in
+ many cases LEX structure and many Item's can't be used in
+ reentrant way now.
+
+ TODO: We can circumvent this problem by using separate
+ sp_head instances for each recursive invocation.
+
+ NOTE: Theoretically arguments of procedure can be evaluated
+ before its invocation so there should be no problem with
+ recursion. But since we perform cleanup for CALL statement
+ as for any other statement only after its execution, its LEX
+ structure is not reusable for recursive calls. Thus we have
+ to prohibit recursion for stored procedures too.
+ */
+ my_error(ER_SP_NO_RECURSION, MYF(0));
+ DBUG_RETURN(-1);
+ }
+ m_is_invoked= TRUE;
+
dbchanged= FALSE;
if (m_db.length &&
(ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged)))
@@ -704,6 +727,7 @@ sp_head::execute(THD *thd)
if (! thd->killed)
ret= sp_change_db(thd, olddb, 0);
}
+ m_is_invoked= FALSE;
DBUG_RETURN(ret);
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index aaef5a3d50e..39b0c1394fe 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -259,6 +259,9 @@ private:
*/
HASH m_sptabs;
+ /* Used for tracking of routine invocations and preventing recursion. */
+ bool m_is_invoked;
+
int
execute(THD *thd);