[php-src] Issue #12107: When running a stored procedure (that returns a result set) twice, PHP crashes

From: Date: Sat, 02 Sep 2023 17:30:05 +0000
Subject: [php-src] Issue #12107: When running a stored procedure (that returns a result set) twice, PHP crashes
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-245317@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/12107 Author: DeveloperRob ### Description The following code: ```php <?php $dbConn = new \mysqli(); // Tests done against a MariaDB 10.6 server $stmt = $dbConn->prepare("call rmh_internal.testSp()"); $stmt->execute(); $stmt->bind_result($output); $stmt->fetch(); echo "Run 1\n"; $stmt->execute(); $stmt->bind_result($output); $stmt->fetch(); echo "Run 2\n"; ``` ```sql DELIMITER $$ CREATE OR REPLACE PROCEDURE rmh_internal.testSp() BEGIN SELECT "String"; END$$ DELIMITER ; ``` Resulted in this output: ``` Run 1 Segmentation fault (core dumped) ``` But I expected this output instead: ``` Run 1 Run 2 ``` GDB Output on core dump: ``` Reading symbols from /usr/bin/php... Reading symbols from /usr/lib/debug/.build-id/d4/2eafeb7fbba34ede1ab24b596f81bbfc38201b.debug... [New LWP 1517127] [New LWP 1517128] [New LWP 1517129] [New LWP 1517130] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Core was generated by `php test2.php'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000ffffba3d7494 in mysqlnd_mysqlnd_stmt_send_execute_pub (s=0xffffba472080, type=<optimized out>, read_cb=<optimized out>, err_cb=<optimized out>) at ./ext/mysqlnd/mysqlnd_ps.c:656 656 ./ext/mysqlnd/mysqlnd_ps.c: No such file or directory. [Current thread is 1 (Thread 0xffffbd0eb020 (LWP 1517127))] (gdb) bt #0 0x0000ffffba3d7494 in mysqlnd_mysqlnd_stmt_send_execute_pub (s=0xffffba472080, type=<optimized out>, read_cb=<optimized out>, err_cb=<optimized out>) at ./ext/mysqlnd/mysqlnd_ps.c:656 #1 0x0000ffffba3d4ec8 in mysqlnd_mysqlnd_stmt_execute_pub (s=0xffffba472080) at ./ext/mysqlnd/mysqlnd_ps.c:618 #2 0x0000ffffb7bdf414 in zif_mysqli_stmt_execute (execute_data=<optimized out>, return_value=0xffffef9cf8a8) at ./ext/mysqli/mysqli_api.c:466 #3 0x0000aaaab02a4de8 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at ./Zend/zend_vm_execute.h:1842 #4 execute_ex (ex=0x0) at ./Zend/zend_vm_execute.h:56076 #5 0x0000aaaab02a7a1c in zend_execute (op_array=0xffffba489000, return_value=<optimized out>) at ./Zend/zend_vm_execute.h:60408 #6 0x0000aaaab0223dd4 in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at ./Zend/zend.c:1833 #7 0x0000aaaab01bccb0 in php_execute_script (primary_file=0x0, primary_file@entry=0xffffef9d1f20) at ./main/main.c:2542 #8 0x0000aaaab031cefc in do_cli (argc=2, argv=0xaaaaccc8fa40) at ./sapi/cli/php_cli.c:964 #9 0x0000aaaab004cc7c in main (argc=2, argv=<optimized out>) at ./sapi/cli/php_cli.c:1333 (gdb) print s->data->result $1 = (MYSQLND_RES *) 0x0 ``` My understanding is that s->m->flush(s); will call mysqlnd_stmt_next_result(s) until there is no more results (and therefore stmt->result->m is empty). However that is the extent of my knowledge, I don't know if stmt->result->m.free_result_buffers(stmt->result); is never needed; or if it should be protected by a if(stmt->result) guard. If someone can provide further guidance, I am happy to open a PR - however I suspect it is either going to be easier for someone to fix themselves OR will be more complicated than I realise here. As a workaround, manually freeing the results in PHP will also prevent the crash (as stmt->result is then no longer truthy) ```php // ... $stmt->free_result(); while($stmt->more_results()){ $stmt->next_result(); $stmt->free_result(); } echo "Run 2\n"; // ... ``` ### PHP Version PHP 8.2.10 / PHP 8.1.23 ### Operating System Ubuntu 22.04.3 LTS / Windows 11 (64bit)

« previous php.bugs (#245317) next »