Description
Description
The following code:
<?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";
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
in mysqlnd_ps.c:648 is then no longer truthy)
// ...
$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)