From: rainer dot jung at kippdata dot de Operating system: Solaris Sparc PHP version: 5.3.18 Package: MSSQL related Bug Type: Bug Bug description:Crash (Bus Error) in mysqlnd due to wrong alignment
Description: ------------ All info refers to PHP 5.3.18. The problem goes back to much older 5.3 versions though. It seems current HEAD contains the same problematic code. The misalignment can happen as soon as mysqlnd.collect_memory_statistics=On. It occurs on Solaris Sparc for 32 Bit builds. It is strictly reproducible on my Solaris 8 system, but not on Solaris 10. This is due to the fact, that a memory allocation for a size that is only divisibleby 4 but not by 8 can return an address only divisible by 4 (this happens on my Solaris 8 system) but it can also return a block of memory starting at an address divisible by 8 (happens by incident on my Solaris 10 system). Crash happens in stack: #0 0x002880f0 in php_mysqlnd_conn_init_pub (conn=0x70dcf4) at /shared/build/autobuild/workdirs/20121021_163211/bld/php53/ext/mysqlnd/mysqlnd.c:2354 No locals. #1 0x002880a0 in _mysqlnd_init (persistent=0 '\0') at /shared/build/autobuild/workdirs/20121021_163211/bld/php53/ext/mysqlnd/mysqlnd.c:2380 ret = (MYSQLND *) 0x70dcf4 #2 0xfee742e0 in php_mysql_do_connect (ht=<value optimized out>, return_value=0x70dc40, return_value_ptr=0x0, this_ptr=<value optimized out>, return_value_used=1, persistent=<value optimized out>) at /shared/build/autobuild/workdirs/20121021_163211/bld/php53/ext/mysql/php_mysql.c:965 index_ptr = (zend_rsrc_list_entry *) 0x70e758 new_index_ptr = {ptr = 0x69e8f0, type = 2778356, refcount = 7393472} user = 0x70db98 "myuser" passwd = 0x70dc00 "mypass" host_and_port = 0x70e808 "myserv:3306" socket = 0x0 tmp = <value optimized out> host = 0x70dc10 "myserv" user_len = 6 passwd_len = 6 host_len = 11 hashed_details = 0x70dc80 "mysql_myserv:3306_myuser_mypass_131072" hashed_details_length = 38 port = 3306 client_flags = 131072 mysql = <value optimized out> free_host = 1 '\001' new_link = 1 '\001' connect_timeout = 60 Analysis shows, that actually the crash happens immediately before entering php_mysqlnd_conn_init_pub(), namely in line 2352 of ext/mysqlnd/mysqlnd.c: 2346 /* {{{ mysqlnd_conn::init */ 2347 static enum_func_status 2348 MYSQLND_METHOD(mysqlnd_conn, init)(MYSQLND * conn TSRMLS_DC) 2349 { 2350 DBG_ENTER("mysqlnd_conn::init"); 2351 mysqlnd_stats_init(&conn->stats, STAT_LAST); 2352 SET_ERROR_AFF_ROWS(conn); The macro SET_ERROR_AFF_ROWS is defined in ext/mysqlnd/mysqlnd_priv.h as: #define SET_ERROR_AFF_ROWS(s) (s)->upsert_status.affected_rows = (uint64_t) ~0 So it is important, that "affected_rows" is aligned correctly for 64 Bits. So lets check the alignment of conn. On my Solaris Sparc system it has size sizeof(MYSQLND), which is 776 so divisible by 8 and the structure should be correctly aligned. But: this is only true if memory statistics for mysqlnd are turned off. If they are turned On, the allocation of conn is actually done for 776 +sizeof(size_t) bytes. This is due to the followinglines in ext/mysqlnd/mysqlnd_debug.c: 814 #define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s)) ... 919 /* {{{ _mysqlnd_pecalloc */ 920 void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D) 921 { ... 932 ret = pecalloc(nmemb, REAL_SIZE(size), persistent); So here instead of allocating 776 bytes, we allocate 776+sizeof(size_t) = 776+4 = 780 bytes which is no longer divisible by 8! So memory allocation not necessarily allocates at 8 bytes alignment. To fix it I expect you need to replace sizeof(size_t) in the following lines by a size that does not reduce alignment for any allocation done in mysqlnd_debug.c. Using sizeof(uint64_t) might suffice for the time being. 814 #define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s)) 815 #define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p)) 816 #define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p)) In HEAD you can find the same problem in file mysqlnd_alloc.c. Note: this problem is *not* the same as the alignment problem in mysqlnd I reported 2.5 years ago in https://bugs.php.net/bug.php?id=51583. Regards, Rainer Test script: --------------- <h2>MySQL Test</h2> <?php ini_set ('display_errors', true); // Enter your database connection info here $db_server = 'myserv'; $db_port = '3306'; $db_name = 'mysql'; $db_username = 'myuser'; $db_password = 'mypass'; echo 'Connecting ...<br>'; $connection = mysql_connect("$db_server:$db_port", $db_username, $db_password, $db_name); if (! $connection) { echo "<br><b>ERROR - Unable to connect to database server '$db_server:$db_port': ". mysql_error() . '</b><br>'; } else { mysql_close($connection); } ?> Actual result: -------------- <h2>MySQL Test</h2> Connecting ...<br>Bus Error (core dumped) -- Edit bug report at https://bugs.php.net/bug.php?id=63327&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=63327&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=63327&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=63327&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=63327&r=fixed Fixed in release: https://bugs.php.net/fix.php?id=63327&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=63327&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=63327&r=needscript Try newer version: https://bugs.php.net/fix.php?id=63327&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=63327&r=support Expected behavior: https://bugs.php.net/fix.php?id=63327&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=63327&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=63327&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=63327&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=63327&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=63327&r=dst IIS Stability: https://bugs.php.net/fix.php?id=63327&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=63327&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=63327&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=63327&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=63327&r=mysqlcfg