Bug #48438 crash with error in unioned query against merge table and view...
Submitted: 30 Oct 2009 14:59 Modified: 18 Jun 2010 2:09
Reporter: Shane Bester (Platinum Quality Contributor) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: MyISAM storage engine Severity:S1 (Critical)
Version:5.1.40, 5.1.41-bzr OS:Any (64-bit XP/linux)
Assigned to: Sergey Vojtovich CPU Architecture:Any

[30 Oct 2009 14:59] Shane Bester
Description:
This is a followup from bug #45796 which should be fixed.

Stack trace from 5.1.40.  both release and debug binaries crash at slightly different places on huge queries.

mysqld-debug.exe!myrg_attach_children()[myrg_open.c:444]
mysqld-debug.exe!ha_myisammrg::attach_children()[ha_myisammrg.cc:549]
mysqld-debug.exe!ha_myisammrg::extra()[ha_myisammrg.cc:949]
mysqld-debug.exe!attach_merge_children()[sql_base.cc:4153]
mysqld-debug.exe!open_tables()[sql_base.cc:4721]
mysqld-debug.exe!open_and_lock_tables_derived()[sql_base.cc:4983]
mysqld-debug.exe!open_and_lock_tables()[mysql_priv.h:1563]
mysqld-debug.exe!execute_sqlcom_select()[sql_parse.cc:5008]
mysqld-debug.exe!mysql_execute_command()[sql_parse.cc:2238]
mysqld-debug.exe!mysql_parse()[sql_parse.cc:5967]
mysqld-debug.exe!dispatch_command()[sql_parse.cc:1226]
mysqld-debug.exe!do_command()[sql_parse.cc:865]
mysqld-debug.exe!handle_one_connection()[sql_connect.cc:1127]
mysqld-debug.exe!pthread_start()[my_winthread.c:85]
mysqld-debug.exe!_callthreadstart()[thread.c:295]
mysqld-debug.exe!_threadstart()[thread.c:277]
kernel32.dll!BaseThreadStart()

How to repeat:
will make a testcase later.
[30 Oct 2009 16:22] MySQL Verification Team
import against 64-bit mysqld.exe on windows, using mysql -uroot --force <bug48438.sql

Attachment: bug48438.sql (application/unknown, text), 55.27 KiB.

[30 Oct 2009 16:43] Valeriy Kravchuk
With 32-bit debug binaries of 5.1.41-bzr on Mac I've got:

77-52-222-60:5.1 openxs$ bin/mysql -uroot -pmysql --force test </Users/openxs/Downloads/bug48438.sql
ERROR 1449 (HY000) at line 339: The user specified as a definer (''@'') does not exist
ERROR 1449 (HY000) at line 351: The user specified as a definer (''@'') does not exist

and no crash.
[30 Oct 2009 18:55] MySQL Verification Team
hm, run server with --skip-grant-tables to avoid that view permissions problem, or just fix the create view statement :)  you should get subquery returns more than 1 row, but second time a crash happens.  i could only repeat this on 64-bit windows 5.1.40.  linux versions didn't crash :-0.
[30 Oct 2009 19:15] Valeriy Kravchuk
With --skip-grant-tables I've got:

77-52-222-60:5.1 openxs$ bin/mysql --force test </Users/openxs/Downloads/bug48438.sql
ERROR 1242 (21000) at line 339: Subquery returns more than 1 row
ERROR 1242 (21000) at line 351: Subquery returns more than 1 row

Still no crash on Mac, but this is expected it seems.
[30 Oct 2009 20:48] MySQL Verification Team
here's the full and original testcase. shows many valgrind errors on linux, crashes windows 5.1.40..

Attachment: bug48438_testcase2.zip (application/zip, text), 159.60 KiB.

[30 Oct 2009 20:56] MySQL Verification Team
valgrind errors (invalid reads of 8 bytes for 64-bit 5.1.40).

Attachment: bug48438_5.1.40_x64_valgrind_testcase2.txt (text/plain), 11.92 KiB.

[1 Nov 2009 12:54] Valeriy Kravchuk
I've got valgrind messages with recent 5.1.41-debug from bzr on 32-bit Linux using last (biggewr) test case:

==6778== Invalid read of size 4
==6778==    at 0x85BD163: mi_get_status (mi_locking.c:289)
==6778==    by 0x86E7DD4: thr_lock (thr_lock.c:667)
==6778==    by 0x86E87EF: thr_multi_lock (thr_lock.c:995)
==6778==    by 0x8289CCD: mysql_lock_tables(THD*, st_table**, unsigned int, unsigned int, bool*) (lock.cc:276)
==6778==    by 0x82F3E63: lock_tables(THD*, TABLE_LIST*, unsigned int, bool*) (sql_base.cc:5300)
==6778==    by 0x82F3441: open_and_lock_tables_derived(THD*, TABLE_LIST*, bool) (sql_base.cc:4994)
==6778==    by 0x82B20DB: open_and_lock_tables(THD*, TABLE_LIST*) (mysql_priv.h:1562)
==6778==    by 0x82AB37E: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5008)
==6778==    by 0x82A357B: mysql_execute_command(THD*) (sql_parse.cc:2238)
==6778==    by 0x82AD721: mysql_parse(THD*, char const*, unsigned int, char const**) (sql_parse.cc:5963)
==6778==    by 0x82A1386: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1224)
==6778==    by 0x82A064F: do_command(THD*) (sql_parse.cc:865)
==6778==  Address 0x565fa90 is 64 bytes inside a block of size 3,996 free'd
==6778==    at 0x401D663: free (vg_replace_malloc.c:325)
==6778==    by 0x86C51D2: _myfree (safemalloc.c:314)
==6778==    by 0x85D2B32: mi_close (mi_close.c:118)
==6778==    by 0x85A7CDD: ha_myisam::close() (ha_myisam.cc:751)
==6778==    by 0x8301889: closefrm(st_table*, bool) (table.cc:1971)
==6778==    by 0x82EA497: intern_close_table(st_table*) (sql_base.cc:781)
==6778==    by 0x82EA558: free_cache_entry(st_table*) (sql_base.cc:803)
==6778==    by 0x86CFADD: my_hash_delete (hash.c:546)
==6778==    by 0x82EB1EF: close_open_tables(THD*) (sql_base.cc:1203)
==6778==    by 0x82EB536: close_thread_tables(THD*) (sql_base.cc:1350)
==6778==    by 0x82A2202: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1619)
==6778==    by 0x82A064F: do_command(THD*) (sql_parse.cc:865)
==6778==
100206 21:56:07 [Note] Got signal 15 to shutdown mysqld
100206 21:56:07 [Note] libexec/mysqld: Normal shutdown

100206 21:56:10  InnoDB: Starting shutdown...
100206 21:56:14  InnoDB: Shutdown completed; log sequence number 0 6970915
100206 21:56:14 [Note] libexec/mysqld: Shutdown complete

==6778==
==6778== HEAP SUMMARY:
==6778==     in use at exit: 1,560 bytes in 16 blocks
==6778==   total heap usage: 49,197 allocs, 49,181 frees, 103,996,817 bytes allocated
==6778==
==6778== LEAK SUMMARY:
==6778==    definitely lost: 0 bytes in 0 blocks
==6778==    indirectly lost: 0 bytes in 0 blocks
==6778==      possibly lost: 748 bytes in 11 blocks
==6778==    still reachable: 812 bytes in 5 blocks
==6778==         suppressed: 0 bytes in 0 blocks
==6778== Rerun with --leak-check=full to see details of leaked memory
==6778==
==6778== For counts of detected and suppressed errors, rerun with: -v
==6778== Use --track-origins=yes to see where uninitialised values come from
==6778== ERROR SUMMARY: 110 errors from 28 contexts (suppressed: 23 from 6)
[1 Nov 2009 12:58] Valeriy Kravchuk
This one (I had many) is more close to what Shane had:

==6778== Invalid read of size 4
==6778==    at 0x85FCD50: myrg_attach_children (myrg_open.c:464)
==6778==    by 0x85F9946: ha_myisammrg::attach_children() (ha_myisammrg.cc:546)
==6778==    by 0x85FAD26: ha_myisammrg::extra(ha_extra_function) (ha_myisammrg.cc:949)
==6778==    by 0x82F1D75: attach_merge_children(TABLE_LIST*) (sql_base.cc:4155)
==6778==    by 0x82F2BE5: open_tables(THD*, TABLE_LIST**, unsigned int*, unsigned int) (sql_base.cc:4717)
==6778==    by 0x82F3399: open_and_lock_tables_derived(THD*, TABLE_LIST*, bool) (sql_base.cc:4985)
==6778==    by 0x82B20DB: open_and_lock_tables(THD*, TABLE_LIST*) (mysql_priv.h:1562)
==6778==    by 0x82AB37E: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:5008)
==6778==    by 0x82A357B: mysql_execute_command(THD*) (sql_parse.cc:2238)
==6778==    by 0x82AD721: mysql_parse(THD*, char const*, unsigned int, char const**) (sql_parse.cc:5963)
==6778==    by 0x82A1386: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1224)
==6778==    by 0x82A064F: do_command(THD*) (sql_parse.cc:865)
[10 Dec 2009 16:33] Kristofer Pettersson
Some observations:

Can only repeat the crash using the big test case on Windows.

Crash happens in myrg_attach_children() which is called from ha_myisammrg::attach_children() during open_and_lock_tables().

A callback function, myisammrg_attach_children_callback(), is ussed to fetch a member variable from the MyISAM handler of the attaching child table: MI_INFO *ha_myisam::file  (fetched through interface ha_myisam::file_ptr())

this MI_INFO-object has an invalid pointer 'MI_STATE_INFO *state' which causes the crash when it is used to get the file length of the table.

There is a corresponing saved_state which works and also MI_INFO::s->state.state is also intact. Using any of these prevent the crash from happening.

The ha_myisam::file attribute is set in mi_open() and reset to NULL in mi_close().

The MI_INFO::state pointer is manipulated by functions found in mi_locking.c
[8 Feb 2010 10:52] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/99577

2847 Sergey Vojtovich	2010-02-08
      BUG#48438 - crash with error in unioned query against merge
                  table and view...
      
      Invalid memory reads after a query referencing MyISAM table
      multiple times with write lock. Invalid memory reads may
      lead to server crash, valgrind warnings, incorrect values
      in INFORMATION_SCHEMA.TABLES.{TABLE_ROWS, DATA_LENGTH,
      INDEX_LENGTH, ...}.
      
      This may happen when one of the table instances gets closed
      after a query, e.g. out of slots in open tables cache. UNION,
      MERGE and VIEW are irrelevant.
      
      The problem was that MyISAM didn't restore state info
      pointer to default value.
     @ myisam/mi_locking.c
        When a query is referencing MyISAM table multiple times
        with a write lock, all table instances share the same
        state info, pointing to MI_INFO::save_state of
        "primary" table instance.
        
        When lock is released, state pointer was restored only
        for the primary table instance. Secondary table instances
        are still pointing to save_state of primary table
        instance.
        
        Primary table instance may get closed, leaving secondary
        table instances state pointer pointing to freed memory.
        
        That's mostly ok, since next lock will update state info
        pointer to correct value. But there're some cases, when
        this secondary table instance state info is accessed
        without a lock, e.g. INFORMATION_SCHEMA, MERGE (in 5.1
        and up), MyISAM itself for DBUG purposes.
        
        Restore default value of state pointer unconditionally,
        for both primary and secondary table instances.
     @ mysql-test/r/myisam.result
        A test case for BUG#48438.
     @ mysql-test/t/myisam.test
        A test case for BUG#48438.
[8 Feb 2010 11:01] Sergey Vojtovich
BUG#45603 was marked as duplicate.
[8 Feb 2010 16:37] Ingo Strüwing
Approved. See email for a small suggestion.
[12 Feb 2010 11:29] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/100114

2847 Sergey Vojtovich	2010-02-12
      BUG#48438 - crash with error in unioned query against merge
                  table and view...
      
      Invalid memory reads after a query referencing MyISAM table
      multiple times with write lock. Invalid memory reads may
      lead to server crash, valgrind warnings, incorrect values
      in INFORMATION_SCHEMA.TABLES.{TABLE_ROWS, DATA_LENGTH,
      INDEX_LENGTH, ...}.
      
      This may happen when one of the table instances gets closed
      after a query, e.g. out of slots in open tables cache. UNION,
      MERGE and VIEW are irrelevant.
      
      The problem was that MyISAM didn't restore state info
      pointer to default value.
     @ myisam/mi_locking.c
        When a query is referencing MyISAM table multiple times
        with a write lock, all table instances share the same
        state info, pointing to MI_INFO::save_state of
        "primary" table instance.
        
        When lock is released, state pointer was restored only
        for the primary table instance. Secondary table instances
        are still pointing to save_state of primary table
        instance.
        
        Primary table instance may get closed, leaving secondary
        table instances state pointer pointing to freed memory.
        
        That's mostly ok, since next lock will update state info
        pointer to correct value. But there're some cases, when
        this secondary table instance state info is accessed
        without a lock, e.g. INFORMATION_SCHEMA, MERGE (in 5.1
        and up), MyISAM itself for DBUG purposes.
        
        Restore default value of state pointer unconditionally,
        for both primary and secondary table instances.
     @ mysql-test/r/myisam.result
        A test case for BUG#48438.
     @ mysql-test/t/myisam.test
        A test case for BUG#48438.
[1 Mar 2010 8:47] Bugs System
Pushed into 5.1.45 (revid:joro@sun.com-20100301083827-xnimmrjg6bh33o1o) (version source revid:joerg@mysql.com-20100212173307-ph563zr4wmoklgwd) (merge vers: 5.1.45) (pib:16)
[2 Mar 2010 14:35] Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20100302142746-u1gxdf5yk2bjrq3e) (version source revid:alik@sun.com-20100225090938-2j5ybqoau570mytu) (merge vers: 6.0.14-alpha) (pib:16)
[2 Mar 2010 14:40] Bugs System
Pushed into 5.5.3-m2 (revid:alik@sun.com-20100302072233-t3uqgjzdukt1pyhe) (version source revid:alexey.kopytov@sun.com-20100221213311-xf5nyv391dsw9v6j) (merge vers: 5.5.2-m2) (pib:16)
[2 Mar 2010 14:45] Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100302072432-k8xvfkgcggkwgi94) (version source revid:alik@sun.com-20100224135227-rcqs9pe9b2in80pf) (pib:16)
[8 Apr 2010 18:17] Paul DuBois
Noted in 5.1.45, 5.5.3, 6.0.14 changelogs.

Invalid memory reads could occur following a query that referenced a
MyISAM tale multiple times with a write lock.
[17 Jun 2010 12:09] Bugs System
Pushed into 5.1.47-ndb-7.0.16 (revid:martin.skold@mysql.com-20100617114014-bva0dy24yyd67697) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[17 Jun 2010 12:56] Bugs System
Pushed into 5.1.47-ndb-6.2.19 (revid:martin.skold@mysql.com-20100617115448-idrbic6gbki37h1c) (version source revid:martin.skold@mysql.com-20100609140708-52rvuyq4q500sxkq) (merge vers: 5.1.45-ndb-6.2.19) (pib:16)
[17 Jun 2010 13:36] Bugs System
Pushed into 5.1.47-ndb-6.3.35 (revid:martin.skold@mysql.com-20100617114611-61aqbb52j752y116) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)