|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-09-30 11:28 UTC] richard dot fussenegger at trivago dot com
Description:
------------
Getting the result of an executed prepared statement that uses a read only cursor results in a segfault because the second close call tries to free the internal result on null. It does not matter which is the first or second close call since stmt gives result a pointer to the result, the one that calls it first is the one that frees it and the other one accesses null.
The access happens in mysqlnd_res::free_result_internal after the if (result->conn) condition where result->conn->m is being called. The m might already point to nowhere because the previous close call already freed it.
Patch will be directly provided as GitHub PR.
Test script:
---------------
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'root', 'keines');
$stmt = $mysqli->prepare('SELECT 1 UNION SELECT 2 UNION SELECT 3');
$stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY);
$stmt->execute();
$result = $stmt->get_result();
// call order does not matter {{{
$result->close();
$stmt->close();
// }}}
$mysqli->close();
Expected result:
----------------
Successful and graceful shutdown of PHP.
Actual result:
--------------
Segfault
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 21:00:01 2025 UTC |
I have a similar problem, but I am not sure if it is the same one. I also get a SEGFAULT when I execute this code: $mysqli = new mysqli($host, $user, $pass, $db); $stmtQuery = $mysqli->prepare("SELECT ?, 'name'"); $stmtQuery->bind_result($id, $name); $stmtQuery->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY); $stmtQuery->bind_param('i', $i); $stmtQuery->execute(); $stmtQuery->get_result()->fetch_assoc(); --------- I could not get the proper backtrace. I only have this if it helps: php7ts!mysqlnd_pfc_free+400 php7ts!mysqlnd_protocol_payload_decoder_factory_free+548 php7ts!mysqlnd_result_buffered_c_init+2c23 php7ts!mysqlnd_result_buffered_c_init+3c2b php_mysqli+1133 php7ts!php_json_parse+2f8b php7ts!mysqlnd_protocol_payload_decoder_factory_free+439a php7ts!mysqlnd_protocol_payload_decoder_factory_free+43f7 php7ts!mysqlnd_result_buffered_c_init+2274 php7ts!mysqlnd_result_buffered_c_init+22b1 php7ts!mysqlnd_pfc_free+2d84 php7ts!ecalloc+b9 php_mysqli!mysqli_objects_new+5a php_mysqli!mysqli_objects_new+2167 php_mysqli!get_module+7591 php7ts!execute_ex+78 php7ts!zend_execute+124 php7ts!zend_execute+152 php7ts!zend_execute_scripts+96 php7ts!zend_set_timeout+90For PHP 7.2, the segfault already happens when the result is freed: php7_debug.dll!mysqlnd_mysqlnd_res_free_result_internal_pub(st_mysqlnd_res * result) Line 348 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\ext\mysqlnd\mysqlnd_result.c:348) php7_debug.dll!mysqlnd_mysqlnd_stmt_free_stmt_result_pub(st_mysqlnd_stmt * const s) Line 2131 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\ext\mysqlnd\mysqlnd_ps.c:2131) php7_debug.dll!mysqlnd_mysqlnd_stmt_free_stmt_content_pub(st_mysqlnd_stmt * const s) Line 2175 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\ext\mysqlnd\mysqlnd_ps.c:2175) php7_debug.dll!mysqlnd_mysqlnd_stmt_close_on_server_priv(st_mysqlnd_stmt * const s, unsigned char implicit) Line 2261 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\ext\mysqlnd\mysqlnd_ps.c:2261) php7_debug.dll!mysqlnd_mysqlnd_stmt_dtor_pub(st_mysqlnd_stmt * const s, unsigned char implicit) Line 2285 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\ext\mysqlnd\mysqlnd_ps.c:2285) php7_debug.dll!zif_mysqli_stmt_close(_zend_execute_data * execute_data, _zval_struct * return_value) Line 2064 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\ext\mysqli\mysqli_api.c:2064) php7_debug.dll!ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(_zend_execute_data * execute_data) Line 908 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\Zend\zend_vm_execute.h:908) php7_debug.dll!execute_ex(_zend_execute_data * ex) Line 59739 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\Zend\zend_vm_execute.h:59739) php7_debug.dll!zend_execute(_zend_op_array * op_array, _zval_struct * return_value) Line 63777 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\Zend\zend_vm_execute.h:63777) php7_debug.dll!zend_execute_scripts(int type, _zval_struct * retval, int file_count, ...) Line 1499 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\Zend\zend.c:1499) php7_debug.dll!php_execute_script(_zend_file_handle * primary_file) Line 2599 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\main\main.c:2599) php.exe!do_cli(int argc, char * * argv) Line 1012 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\sapi\cli\php_cli.c:1012) php.exe!main(int argc, char * * argv) Line 1403 (c:\php-sdk\phpdev\vc15\x64\php-src-7.2\sapi\cli\php_cli.c:1403) php.exe!invoke_main() Line 79 (d:\agent\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:79) php.exe!__scrt_common_main_seh() Line 288 (d:\agent\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288) php.exe!__scrt_common_main() Line 331 (d:\agent\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:331) php.exe!mainCRTStartup() Line 17 (d:\agent\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:17) kernel32.dll!00007ffeba257bd4() (Unbekannte Quelle:0) ntdll.dll!00007ffebadece71() (Unbekannte Quelle:0) I set a breakpoint on mysqlnd_result.c:1527[1], and did p result->conn // 0x0000016afac76500 n p result->conn // 0x0000016afac9c180 @tekiela246, your problem doesn't seem related to this issue, so please file a new ticket. [1] <https://github.com/php/php-src/blob/php-7.2.21/ext/mysqlnd/mysqlnd_result.c#L1527>