MySQL Lists are EOL. Please join:

List:Internals« Previous MessageNext Message »
From:dlenev Date:July 1 2005 9:01am
Subject:bk commit into 5.0 tree (dlenev:1.1989) BUG#11600
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of dlenev. When dlenev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1989 05/07/01 13:01:46 dlenev@stripped +7 -0
  "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.

  sql/sp_head.h
    1.59 05/07/01 13:01:38 dlenev@stripped +3 -0
    sp_head:
      Added m_is_invoked member for tracking of routine invocations and
      preventing recursion.

  sql/sp_head.cc
    1.152 05/07/01 13:01:38 dlenev@stripped +25 -1
    sp_head::execute():
      Since many Item's and LEX members can't be used in reentrant fashion
      we have to disable recursion for stored routines. So let us track
      routine invocations using sp_head::m_is_invoked member and raise
      error when one attempts to call routine recursively.
      

  sql/share/errmsg.txt
    1.36 05/07/01 13:01:38 dlenev@stripped +2 -0
    Added error message saying that recursive stored routines are disallowed.

  mysql-test/t/sp.test
    1.125 05/07/01 13:01:37 dlenev@stripped +70 -66
    Disabled test cases containing recursive stored routines until we will
    support for them.

  mysql-test/t/sp-error.test
    1.74 05/07/01 13:01:37 dlenev@stripped +55 -0
    Added tests for bug #11394 "Recursion in SP crash server" and
    bug #11600 "Stored procedures: crash with function calling itself".
    (We simply disallow recursion for stored routines).

  mysql-test/r/sp.result
    1.130 05/07/01 13:01:37 dlenev@stripped +0 -68
    Disabled test cases containing recursive stored routines until we will
    support for them.

  mysql-test/r/sp-error.result
    1.72 05/07/01 13:01:37 dlenev@stripped +40 -0
    Added tests for bug #11394 "Recursion in SP crash server" and
    bug #11600 "Stored procedures: crash with function calling itself".
    (We simply disallow recursion for stored routines).

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	dlenev
# Host:	brandersnatch.localdomain
# Root:	/home/dlenev/src/mysql-5.0-bg11394

--- 1.35/sql/share/errmsg.txt	Mon Jun 27 15:12:09 2005
+++ 1.36/sql/share/errmsg.txt	Fri Jul  1 13:01:38 2005
@@ -5358,3 +5358,5 @@
 	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."

--- 1.71/mysql-test/r/sp-error.result	Thu Jun  9 01:46:18 2005
+++ 1.72/mysql-test/r/sp-error.result	Fri Jul  1 13:01:37 2005
@@ -686,3 +686,43 @@
 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|

--- 1.129/mysql-test/r/sp.result	Wed Jun 22 01:17:04 2005
+++ 1.130/mysql-test/r/sp.result	Fri Jul  1 13:01:37 2005
@@ -1396,60 +1396,6 @@
 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 @@
 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()

--- 1.73/mysql-test/t/sp-error.test	Thu Jun  9 01:46:18 2005
+++ 1.74/mysql-test/t/sp-error.test	Fri Jul  1 13:01:37 2005
@@ -986,3 +986,58 @@
 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 |;

--- 1.124/mysql-test/t/sp.test	Wed Jun 22 01:17:04 2005
+++ 1.125/mysql-test/t/sp.test	Fri Jul  1 13:01:37 2005
@@ -1630,54 +1630,56 @@
 
 
 # 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 @@
 #
 # 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

--- 1.151/sql/sp_head.cc	Wed Jun 29 12:49:35 2005
+++ 1.152/sql/sp_head.cc	Fri Jul  1 13:01:38 2005
@@ -312,7 +312,8 @@
 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 @@
     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 @@
     if (! thd->killed)
       ret= sp_change_db(thd, olddb, 0);
   }
+  m_is_invoked= FALSE;
   DBUG_RETURN(ret);
 }
 

--- 1.58/sql/sp_head.h	Thu Jun 23 20:22:02 2005
+++ 1.59/sql/sp_head.h	Fri Jul  1 13:01:38 2005
@@ -259,6 +259,9 @@
   */
   HASH m_sptabs;
 
+  /* Used for tracking of routine invocations and preventing recursion. */
+  bool m_is_invoked;
+
   int
   execute(THD *thd);
 
Thread
bk commit into 5.0 tree (dlenev:1.1989) BUG#11600dlenev1 Jul