Bug #13714 Server crash calling a nested call to a function
Submitted: 3 Oct 2005 13:45 Modified: 10 Nov 2005 9:31
Reporter: Giorgio Calderone Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: Stored Routines Severity:S3 (Non-critical)
Version:5.0.13/5.0.15 BK source OS:GNU/Linux (SuSE 9.2)
Assigned to: Assigned Account CPU Architecture:Any

[3 Oct 2005 13:45] Giorgio Calderone
Description:
MySQL server crashes when calling a function inside a procedure that hasn't
been called yet since the server has started, or the external procedure was 
created.

This bug is probably different from #13549, here we have a workaround.

IMPORTANT:
With version 5.0.11 everything works fine. The bug is in versions 5.0.12 and
5.0.13.

How to repeat:
delimiter //

#
#Create a database for the test
#
DROP DATABASE IF EXISTS myrotest//
CREATE DATABASE myrotest//
USE myrotest

#
#Create support table. These tables stores information
#about user and groups, something similar to what happen
#for linux accounts:
#
#Table my_usr: user description
#Table my_grp: group description
#Table my_usrgrp: users belonging to groups
#
DROP TABLE IF EXISTS my_usr//
CREATE TABLE my_usr(uid      TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
                    usr      CHAR(20) NOT NULL,
                    PRIMARY KEY(uid),
                    UNIQUE KEY(usr))//

DROP TABLE IF EXISTS my_grp//
CREATE TABLE my_grp(gid    TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
                    grp    CHAR(20) NOT NULL,
                    PRIMARY KEY(gid),
                    UNIQUE KEY(grp))//

DROP TABLE IF EXISTS my_usrgrp//
CREATE TABLE my_usrgrp(uid  TINYINT UNSIGNED NOT NULL,
                       gid  TINYINT UNSIGNED NOT NULL,
                       UNIQUE KEY(uid, gid))//

#
#Insert some values: user 'root', group 'admin', user 'root' member
#of 'admin'.
#
INSERT INTO my_usr(usr) VALUES('root')//
INSERT INTO my_grp(grp) VALUES('admin')//
INSERT INTO my_usrgrp   VALUES (1, 1)//

#
#This function translates a group id (gid) to the name of the group.
#
DROP FUNCTION IF EXISTS myf_gid2grp//
CREATE FUNCTION myf_gid2grp(p_gid TINYINT UNSIGNED) RETURNS CHAR(20)
  NOT DETERMINISTIC
  BEGIN
        RETURN (SELECT grp FROM my_grp WHERE gid=p_gid);
  END//

#
#This function returns a list of groups a user (identified by the parameter)
#belongs to.
#
DROP FUNCTION IF EXISTS myf_listGroups//
CREATE FUNCTION myf_listGroups(p_uid TINYINT UNSIGNED) RETURNS VARCHAR(200)
   NOT DETERMINISTIC
   BEGIN
     DECLARE a CHAR(20);
     DECLARE res VARCHAR(200);
     DECLARE eof INT DEFAULT 0;
     DECLARE c CURSOR FOR SELECT gid FROM my_usrgrp WHERE uid=p_uid;
     DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET eof = 1;

     OPEN c;
     SET res='';

     REPEAT
       FETCH c INTO a;
       IF ((NOT eof)  AND  (NOT ISNULL(a))) THEN
         SET res = CONCAT(res, CONCAT(myf_gid2grp(a), ' '));
       END IF;
     UNTIL eof END REPEAT;
     CLOSE c;

     RETURN res;
   END//

#
#This procedures report a list of all users, along with the groups
#they are member of.
#
DROP PROCEDURE IF EXISTS myp_users//
CREATE PROCEDURE myp_users()
   NOT DETERMINISTIC
   BEGIN
     SELECT uid, usr,
            myf_listGroups(uid) as addgrp
            FROM my_usr;
   END//

#
#Calling myp_users() leads to a server crash
#
call myp_users()//

#
#Instead if we call myf_listGroups() before, everithing works:
#
select myf_listGroups(1)//
call myp_users()//

Suggested fix:
The workaround is to make a dummy call the inner function 
before calling the outer procedure.
[3 Oct 2005 14:06] MySQL Verification Team
miguel@hegel:~/dbs/5.0> bin/mysql -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2 to server version: 5.0.15-rc-debug

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> USE myrotest
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> call myp_users();
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> 

051003 10:59:25 [Note] /home/miguel/dbs/5.0/libexec/mysqld: ready for connections.
Version: '5.0.15-rc-debug'  socket: '/tmp/mysql.sock'  port: 3306  Source distribution
[New Thread 1132456880 (LWP 6922)]
[Thread 1132456880 (zombie) exited]
[New Thread 1132456880 (LWP 6943)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1132456880 (LWP 6943)]
0x0814c9a9 in Item_splocal::type (this=0x8e80fb0) at item.cc:896
896         return thd->spcont->get_item(m_offset)->type();
(gdb) bt full
#0  0x0814c9a9 in Item_splocal::type (this=0x8e80fb0) at item.cc:896
        thd = (class THD *) 0x8e38290
#1  0x081fa6aa in negate_expression (thd=0x8e38290, expr=0x8e80fb0) at sql_parse.cc:7411
        negated = (class Item *) 0x820d634
#2  0x082037b5 in yyparse (yythd=0x8e38290) at sql_yacc.yy:4256
        yychar = 41
        yylval = {num = 149422165, ulong_num = 149422165, ulonglong_number = 4444389461, lex_str = {
<cut>
[10 Nov 2005 9:31] Dmitry Lenev
Hi, Giorgio!

Thank you for your bug-report!
After investigation I think that this bug is duplicate of bug #13549  "Server crash with nested stored procedures" so I am marking it as such.