php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69899 segfault on close() after free_result() with mysqlnd
Submitted: 2015-06-22 13:06 UTC Modified: 2015-06-24 05:31 UTC
Votes:3
Avg. Score:4.3 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:2 (66.7%)
From: phpnet at sitebytes dot nl Assigned: mysql
Status: Closed Package: MySQL related
PHP Version: 5.6.10 OS: linux
Private report: No CVE-ID:
 [2015-06-22 13:06 UTC] phpnet at sitebytes dot nl
Description:
------------
When using mysqlnd, the provided test script segfaults. This does not happen using libmysqlclient.
The segfault also does *not* happen (with mysqlnd) if we don't use a separate function of when we skip the free_result() call.

This is tested on debian (5.6.9+dfsg-0+deb8u1) as well as on centos (5.5.26 and 5.6.10 segfault, version 5.4.42 produces a warning, and 5.3.3 (without mysqlnd) seems to be OK).

gdb output (on debian) is:

GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/php5...Reading symbols from /usr/lib/debug/.build-id/14/e7d090b7a7289441496c5aa501c501008e4d7a.debug...done.
done.
(gdb) r
Starting program: /usr/bin/php5 SegfaultTest.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
free result
close

Program received signal SIGSEGV, Segmentation fault.
0x00000000006a0f8a in _php_stream_write (stream=0x0, buf=0x7ffff7fcc438 "\005", count=9) at /tmp/buildd/php5-5.6.9+dfsg/main/streams/streams.c:1236
1236    /tmp/buildd/php5-5.6.9+dfsg/main/streams/streams.c: No such file or directory.
(gdb) bt
#0  0x00000000006a0f8a in _php_stream_write (stream=0x0, buf=0x7ffff7fcc438 "\005", count=9) at /tmp/buildd/php5-5.6.9+dfsg/main/streams/streams.c:1236
#1  0x00007ffff3c6c70e in php_mysqlnd_net_send_ex_pub (net=0x7ffff7fcba10, buffer=<optimized out>, count=5, conn_stats=0x114e720, error_info=0x7ffff7fca4e8)
    at /tmp/buildd/php5-5.6.9+dfsg/ext/mysqlnd/mysqlnd_net.c:422
#2  0x00007ffff3c65180 in php_mysqlnd_cmd_write (_packet=0x7ffff7fcb2f8, conn=0x7ffff7fca3b0) at /tmp/buildd/php5-5.6.9+dfsg/ext/mysqlnd/mysqlnd_wireprotocol.c:1014
#3  0x00007ffff3c5c399 in php_mysqlnd_conn_data_simple_command_send_request_pub (conn=0x7ffff7fca3b0, command=<optimized out>, arg=<optimized out>, arg_len=<optimized out>, silent=<optimized out>, 
    ignore_upsert_status=<optimized out>) at /tmp/buildd/php5-5.6.9+dfsg/ext/mysqlnd/mysqlnd.c:356
#4  0x00007ffff3c5a1fe in php_mysqlnd_conn_data_simple_command_pub (conn=0x7ffff7fca3b0, command=COM_STMT_CLOSE, arg=<optimized out>, arg_len=<optimized out>, ok_packet=PROT_LAST, silent=0 '\000', 
    ignore_upsert_status=1 '\001') at /tmp/buildd/php5-5.6.9+dfsg/ext/mysqlnd/mysqlnd.c:381
#5  0x00007ffff3c78e97 in php_mysqlnd_stmt_net_close_priv (s=0x7ffff7fc93a8, implicit=56 '8') at /tmp/buildd/php5-5.6.9+dfsg/ext/mysqlnd/mysqlnd_ps.c:2209
#6  0x00007ffff3c78145 in php_mysqlnd_stmt_dtor_pub (s=0x7ffff7fc93a8, implicit=<optimized out>) at /tmp/buildd/php5-5.6.9+dfsg/ext/mysqlnd/mysqlnd_ps.c:2261
#7  0x00007ffff31f8a1d in zif_mysqli_stmt_close (ht=<optimized out>, return_value=0x7ffff7fc85a0, return_value_ptr=<optimized out>, this_ptr=<optimized out>, return_value_used=<optimized out>)
    at /tmp/buildd/php5-5.6.9+dfsg/ext/mysqli/mysqli_api.c:2116
#8  0x00000000006dabda in dtrace_execute_internal (execute_data_ptr=<optimized out>, fci=<optimized out>, return_value_used=<optimized out>) at /tmp/buildd/php5-5.6.9+dfsg/Zend/zend_dtrace.c:97
#9  0x000000000079a370 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7f95200) at /tmp/buildd/php5-5.6.9+dfsg/Zend/zend_vm_execute.h:560
#10 0x0000000000728da0 in execute_ex (execute_data=0x7ffff7f95200) at /tmp/buildd/php5-5.6.9+dfsg/Zend/zend_vm_execute.h:363
#11 0x00000000006daa78 in dtrace_execute_ex (execute_data=0x7ffff7f95200) at /tmp/buildd/php5-5.6.9+dfsg/Zend/zend_dtrace.c:73
#12 0x00000000006ed570 in zend_execute_scripts (type=0, type@entry=8, retval=0x7ffff7fcc438, retval@entry=0x0, file_count=9, file_count@entry=3) at /tmp/buildd/php5-5.6.9+dfsg/Zend/zend.c:1341
#13 0x00000000006892e0 in php_execute_script (primary_file=0x7fffffffcf10) at /tmp/buildd/php5-5.6.9+dfsg/main/main.c:2597
#14 0x000000000079c310 in do_cli (argc=0, argv=0x7ffff7fcc438) at /tmp/buildd/php5-5.6.9+dfsg/sapi/cli/php_cli.c:994
#15 0x000000000046286d in main (argc=0, argv=0x7ffff7fcc438) at /tmp/buildd/php5-5.6.9+dfsg/sapi/cli/php_cli.c:1378
(gdb)



Just for reference, the database is not really interesting; it's freshly created with one (empty) table:
mysql> show create table test;
+-------+---------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                      |
+-------+---------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (
  `id` int(11) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+---------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from test;
Empty set (0.01 sec)

mysql> 



Test script:
---------------
<?php
function create_sth(){
        $dbh = new mysqli('localhost', 'testuser', 'testpass', 'testdb', 3306);
        $sth = $dbh->prepare('SELECT * FROM test');
        if ( $dbh->errno ){
                error_log(var_export($dbh->error_list, true));
        }
        return $sth;
}
$sth = create_sth();
error_log("free result");
$sth->free_result();
error_log("close");
$sth->close();
error_log('Finished !');
?>


Expected result:
----------------
free result
close
Finished !


Actual result:
--------------
debian (5.6.9) and centos (5.5.26 and 5.6.10) both produce a segfault when calling close()

free result
close
Segmentation fault

php 5.4.42 only produces a warning, but completes the script

free result
close
PHP Warning:  Error while sending STMT_CLOSE packet. PID=3182 in /home/siteadmin/SegfaultTest.php on line 14
Finished !


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-24 05:31 UTC] laruence@php.net
-Assigned To: +Assigned To: mysql
 [2015-06-24 05:31 UTC] laruence@php.net
I got a fix, but needs @mysql guys's reviewing...  

---------------------------------------------------------------------
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 4ae8cdd..ac4f048 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -1948,8 +1948,10 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s TSRMLS_DC)
 		stmt->state = MYSQLND_STMT_PREPARED;
 	}

-	/* Line is free! */
-	CONN_SET_STATE(stmt->conn, CONN_READY);
+	if (CONN_GET_STATE(stmt->conn) != CONN_QUIT_SENT) {
+		/* Line is free! */
+		CONN_SET_STATE(stmt->conn, CONN_READY);
+	}

 	DBG_RETURN(PASS);
 }
 [2016-11-21 08:06 UTC] exsystemchina at gmail dot com
Same situation for PHP7, CentOS Linux release 7.2.1511 (Core) 

PHP 7.0.12 (cli) (built: Oct 23 2016 00:17:02) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
 [2017-01-12 20:17 UTC] nikic@php.net
Automatic comment on behalf of richard.fussenegger@trivago.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=bd75f9e61375c7632bb55b0d49b470ecd94e8ec7
Log: Fix bug #69899
 [2017-01-12 20:17 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2017-01-12 20:17 UTC] nikic@php.net
Automatic comment on behalf of richard.fussenegger@trivago.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=bd75f9e61375c7632bb55b0d49b470ecd94e8ec7
Log: Fix bug #69899
 [2017-01-12 20:17 UTC] nikic@php.net
Automatic comment on behalf of richard.fussenegger@trivago.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=bd75f9e61375c7632bb55b0d49b470ecd94e8ec7
Log: Fix bug #69899
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Mon Feb 20 22:01:35 2017 UTC