Bug #10016 Uninit memory touched if SPs and cursors are used
Submitted: 19 Apr 2005 21:37 Modified: 9 Sep 2005 13:24
Reporter: Jan Kneschke Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:5.0.4 OS:Linux (Linux/x86)
Assigned to: CPU Architecture:Any

[19 Apr 2005 21:37] Jan Kneschke
Description:
This is the some SP as used in bug #10015. Only the storage engine is replaced.

This might not be a real bug that is causing a real problem. It just might be related to #10015.

How to repeat:
DROP TABLE IF EXISTS test10;
CREATE TABLE test10 (
  id INT UNSIGNED NOT NULL auto_increment PRIMARY KEY,
  name VARCHAR(128),
  parent_id INT UNSIGNED
) engine=MyISAM;

# insert the base-node
INSERT INTO test10 VALUES
  ( 1, 'Earth', NULL ),
  ( 2, 'Moon', NULL );

# how deep is the tree
DROP FUNCTION IF EXISTS sp_tree_depth;
DELIMITER $$
CREATE FUNCTION sp_tree_depth(nid INT UNSIGNED)
  RETURNS INT UNSIGNED
BEGIN
  DECLARE depth INT UNSIGNED DEFAULT 0;
  DECLARE n INT UNSIGNED DEFAULT 0;
  DECLARE maxdepth INT UNSIGNED DEFAULT 0;
  DECLARE done INT UNSIGNED DEFAULT 0;
  DECLARE cur CURSOR FOR SELECT id FROM test10 WHERE parent_id = nid;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN cur;
l: LOOP
    FETCH cur INTO n;

    IF done = 1 THEN
      LEAVE l;
    END IF;
    SELECT sp_tree_depth(n)+1 FROM test10 INTO depth;
    IF depth > maxdepth THEN
      SET maxdepth = depth;
    END IF;
  END LOOP;
  CLOSE cur;

  RETURN maxdepth;
END$$
DELIMITER ;
SELECT sp_tree_depth(1) FROM test10;

==12470== Thread 11:
==12470== Syscall param pwrite64(buf) points to uninitialised byte(s)
==12470==    at 0x83B1C97: __libc_pwrite64 (../sysdeps/unix/sysv/linux/pwrite64.c:51)
==12470==    by 0x838F6C2: pwrite64 (wrapsyscall.c:147)
==12470==    by 0x834C9FB: my_pwrite (my_pread.c:101)
==12470==    by 0x834F6A7: flush_cached_blocks (mf_keycache.c:2142)
==12470==    by 0x834FB27: flush_key_blocks_int (mf_keycache.c:2319)
==12470==    by 0x834FD52: flush_key_blocks (mf_keycache.c:2408)
==12470==    by 0x8319135: mi_lock_database (mi_locking.c:64)
==12470==    by 0x814A5CE: ha_myisam::external_lock(THD *, int) (ha_myisam.cc:1318)
==12470==    by 0x809E360: unlock_external(THD *, st_table **, unsigned int) (lock.cc:377)
==12470==    by 0x809DE5E: mysql_unlock_tables(THD *, st_mysql_lock *) (lock.cc:209)
==12470==    by 0x80FFE38: mysql_insert(THD *, st_table_list *, List<Item> &, List<List<Item> > &, List<Item> &, List<It
em> &, enum_duplicates, bool) (sql_insert.cc:468)
==12470==    by 0x80B7386: mysql_execute_command(THD *) (sql_parse.cc:3142)
==12470==  Address 0x1C8982EC is not stack'd, malloc'd or (recently) free'd

Suggested fix:
init memory
[20 Apr 2005 19:14] MySQL Verification Team
I got different Valgrind report running 5.0.5 BK source on Slackware 10.1
and testing on Windows Purify not shows that issue:

==2647==
==2647== Syscall param write(buf) points to uninitialised byte(s)
==2647==    at 0x1BA86132: pthread_key_delete (in /lib/libpthread-0.10.so)
==2647==    by 0x85D3967: my_thread_global_end (my_thr_init.c:108)
==2647==    by 0x85AE94B: my_end (my_init.c:188)
==2647==    by 0x81E3A2E: main (mysqld.cc:3218)
==2647==  Address 0x52BFE38C is on thread 1's stack
==2647== discard syms at 0x1BD5D000-0x1BD67000 in /lib/libnss_files-2.3.4.so due to munmap()
==2647==
==2647== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 49 from 7)
==2647==
==2647== 1 errors in context 1 of 2:
==2647== Syscall param write(buf) points to uninitialised byte(s)
==2647==    at 0x1BA86132: pthread_key_delete (in /lib/libpthread-0.10.so)
==2647==    by 0x85D3967: my_thread_global_end (my_thr_init.c:108)
==2647==    by 0x85AE94B: my_end (my_init.c:188)
==2647==    by 0x81E3A2E: main (mysqld.cc:3218)
==2647==  Address 0x52BFE38C is on thread 1's stack
==2647==
==2647== 1 errors in context 2 of 2:
==2647== Conditional jump or move depends on uninitialised value(s)
==2647==    at 0x85DE21B: strstr (in /home/miguel/dbs/5.0/libexec/mysqld)
==2647==    by 0x1BA8A674: (within /lib/libpthread-0.10.so)
==2647==    by 0x1BA80A9D: (within /lib/libpthread-0.10.so)
==2647==    by 0x1B8EEAAD: call_init (in /lib/ld-2.3.4.so)
==2647==    by 0x1B8EE9AA: _dl_init (in /lib/ld-2.3.4.so)
==2647==    by 0x1B8E47D4: (within /lib/ld-2.3.4.so)
--2647--
--2647-- supp:    1 LinuxThreads: write/__pthread_initialize_manager/pthread_create
--2647-- supp:   13 LinuxThreads: write/pthread_create
--2647-- supp:    1 LinuxThreads: write/pthread_onexit_process
--2647-- supp:    1 LinuxThread clone use (tlsinfo)
--2647-- supp:    1 LinuxThread clone use (child_tidptr)
--2647-- supp:    1 LinuxThread clone use (parent_tidptr)
--2647-- supp:   31 dl_relocate_object
==2647==
==2647== IN SUMMARY: 2 errors from 2 contexts (suppressed: 49 from 7)
==2647==
==2647== malloc/free: in use at exit: 19956636 bytes in 40110 blocks.
==2647== malloc/free: 40825 allocs, 715 frees, 48202114 bytes allocated.
==2647==
==2647== searching for pointers to 40110 not-freed blocks.
==2647== checked 38609852 bytes.
==2647==
==2647== LEAK SUMMARY:
==2647==    definitely lost: 8160 bytes in 1 blocks.
==2647==      possibly lost: 0 bytes in 0 blocks.
==2647==    still reachable: 19948476 bytes in 40109 blocks.
==2647==         suppressed: 0 bytes in 0 blocks.
==2647== Use --leak-check=full to see details of leaked memory.
--2647--     TT/TC: 0 tc sectors discarded.
--2647--            33714 tt_fast misses.
--2647-- translate: new     29790 (586225 -> 7189852; ratio 122:10)
--2647--            discard 143 (1789 -> 25984; ratio 145:10).
--2647-- chainings: 20185 chainings, 0 unchainings.
--2647--  dispatch: 68820056 jumps (bb entries); of them 9858438 (14%) unchained.
--2647--            1386/78530 major/minor sched events.
--2647-- reg-alloc: 5731 t-req-spill, 1216345+39621 orig+spill uis,
--2647--            148991 total-reg-rank
--2647--    sanity: 1387 cheap, 56 expensive checks.
--2647--    ccalls: 145872 C calls, 54% saves+restores avoided (470562 bytes)
--2647--            202508 args, avg 0.87 setup instrs each (51970 bytes)
--2647--            0% clear the stack (437616 bytes)
--2647--            59371 retvals, 23% of reg-reg movs avoided (27002 bytes)
miguel@light:~/dbs/5.0$
[26 May 2005 10:05] Michael Widenius
Jan, can you verify that you compiled MySQL with -DHAVE_purify defined.
Becasue if you didn't do this, the warning in my_pwrite() is ok (as we don't initialize the MyISAM page buffers when not using valgrind as this isn't needed during not valgrind runs)

(Miguel's test case doesn't show any errors in read/write that may be releated)

I agree that in theory this could be a bug in stack space detection and we have a memory overrun, but we need more data to know what is going one.
[26 May 2005 21:02] Jan Kneschke
It is the binary debug tar.gz from the download page. The build-team says that HAVE_purify is not enabled in that package.
[26 Jun 2005 23:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[9 Sep 2005 13:24] Valeriy Kravchuk
Can't repeat it on today's 5.0.13-BK on Linux:

mysql> CREATE TABLE test10 (
    ->   id INT UNSIGNED NOT NULL auto_increment PRIMARY KEY,
    ->   name VARCHAR(128),
    ->    parent_id INT UNSIGNED
    -> ) engine=MyISAM;
Query OK, 0 rows affected (0,03 sec)

mysql> INSERT INTO test10 VALUES
    ->   ( 1, 'Earth', NULL ),
    ->   ( 2, 'Moon', NULL );
Query OK, 2 rows affected (0,00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> DROP FUNCTION IF EXISTS sp_tree_depth;
DELIMITER $$
CQuery OK, 0 rows affected, 1 warning (0,03 sec)

mysql> DELIMITER $$
mysql> CREATE FUNCTION sp_tree_depth(nid INT UNSIGNED)
    ->   RETURNS INT UNSIGNED
    -> BEGIN
    ->   DECLARE depth INT UNSIGNED DEFAULT 0;
    ->   DECLARE n INT UNSIGNED DEFAULT 0;
    ->   DECLARE maxdepth INT UNSIGNED DEFAULT 0;
    ->   DECLARE done INT UNSIGNED DEFAULT 0;
    ->    DECLARE cur CURSOR FOR SELECT id FROM test10 WHERE parent_id = nid;
    ->   DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    ->
    ->   OPEN cur;
    -> l: LOOP
    ->     FETCH cur INTO n;
    ->
    ->     IF done = 1 THEN
    ->        LEAVE l;
    ->     END IF;
    ->     SELECT sp_tree_depth(n)+1 FROM test10 INTO depth;
    ->     IF depth > maxdepth THEN
    ->       SET maxdepth = depth;
    ->     END IF;
    ->   END LOOP;
    ->    CLOSE cur;
    ->
    ->   RETURN maxdepth;
    -> END$$
DELIMITER ;Query OK, 0 rows affected (0,04 sec)

mysql> DELIMITER ;
mysql> select version();
+-------------------+
| version()         |
+-------------------+
| 5.0.13-beta-debug |
+-------------------+
1 row in set (0,00 sec)

mysql> SELECT sp_tree_depth(1) FROM test10;
+------------------+
| sp_tree_depth(1) |
+------------------+
|                0 |
|                0 |
+------------------+
2 rows in set (0,00 sec)

Please, try newer verison of MySQL.