Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When running a stored procedure (that returns a result set) twice, PHP crashes #12107

Closed
DeveloperRob opened this issue Sep 2, 2023 · 1 comment

Comments

@DeveloperRob
Copy link

DeveloperRob commented Sep 2, 2023

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)

@nielsdos
Copy link
Member

Thanks for the analysis, I opened a PR.

nielsdos added a commit that referenced this issue Jan 19, 2024
* PHP-8.2:
  Fix GH-12107: When running a stored procedure (that returns a result set) twice, PHP crashes
nielsdos added a commit that referenced this issue Jan 19, 2024
* PHP-8.3:
  Fix GH-13177: PHP 8.3.2: final private constructor not allowed when used in trait
  Fix GH-12107: When running a stored procedure (that returns a result set) twice, PHP crashes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants