]> granicus.if.org Git - php/commitdiff
Fixed bug #76815
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 10 Dec 2020 10:21:06 +0000 (11:21 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 10 Dec 2020 10:23:41 +0000 (11:23 +0100)
When we receive an error while reading a result set, we should
assume that no more result sets are available. libmysqlclient
implements the same behavior.

NEWS
ext/mysqlnd/mysqlnd_result.c
ext/pdo_mysql/tests/bug76815.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 7eeea0c40023240802118f2727a88eacef2efb91..20f7da0f02ac95fbb36f85dfb2fa55e231ab0348 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -40,6 +40,8 @@ PHP                                                                        NEWS
     queries"). (Nikita)
   . Fixed bug #71145 (Multiple statements in init command triggers unbuffered
     query error). (Nikita)
+  . Fixed bug #76815 (PDOStatement cannot be GCed/closeCursor-ed when a
+    PROCEDURE resultset SIGNAL). (Nikita)
 
 - Phpdbg:
   . Fixed bug #76813 (Access violation near NULL on source operand). (cmb)
index 46d308d1f9bfd5d69af9995605a3b694676f950f..8a3ebb53a77e55c962e5ba8e80456ab4ede4d759 100644 (file)
@@ -1359,6 +1359,13 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
                UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet.server_status);
        }
 
+       if (ret == FAIL) {
+               /* Error packets do not contain server status information. However, we know that after
+                * an error there will be no further result sets. */
+               UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status,
+                       UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & ~SERVER_MORE_RESULTS_EXISTS);
+       }
+
        /* save some memory */
        if (free_rows) {
                /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
diff --git a/ext/pdo_mysql/tests/bug76815.phpt b/ext/pdo_mysql/tests/bug76815.phpt
new file mode 100644 (file)
index 0000000..b5c8577
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Bug #76815: PDOStatement cannot be GCed/closeCursor-ed when a PROCEDURE resultset SIGNAL
+--SKIPIF--
+<?php
+require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
+require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+MySQLPDOTest::skip();
+?>
+--FILE--
+<?php
+require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+
+$pdo = MySQLPDOTest::factory();
+$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$pdo->query('DROP FUNCTION IF EXISTS tst');
+$pdo->query('DROP PROCEDURE IF EXISTS tst2');
+$pdo->query('CREATE FUNCTION tst() RETURNS VARCHAR(5) DETERMINISTIC BEGIN RETURN \'x12345\'; END');
+$pdo->query('CREATE PROCEDURE tst2() BEGIN SELECT tst(); END');
+
+$st = $pdo->prepare('CALL tst2()');
+try {
+    $st->execute();
+} catch (PDOException $ex) {
+    echo $ex->getMessage(), "\n";
+}
+unset($st);
+echo "Ok.\n";
+
+?>
+--EXPECT--
+SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'tst()' at row 1
+Ok.