]> granicus.if.org Git - php/commitdiff
Fix invalid free of persistent results on error/connection loss in mysqlnd (bug 74376)
authorYussuf Khalil <dev@pp3345.net>
Wed, 5 Apr 2017 18:57:03 +0000 (20:57 +0200)
committerYussuf Khalil <dev@pp3345.net>
Wed, 5 Apr 2017 18:57:03 +0000 (20:57 +0200)
ext/mysqlnd/mysqlnd_ps.c
ext/pdo_mysql/tests/bug_74376.phpt [new file with mode: 0644]

index 2631e4a797850bd53acbfe5d7c3d212f1c2ed388..52a06d7615907ad664c3211c66cae994674cb4f9 100644 (file)
@@ -129,7 +129,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
        } else {
                COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
                stmt->result->m.free_result_contents(stmt->result);
-               mnd_efree(stmt->result);
+               mnd_pefree(stmt->result, stmt->result->persistent);
                stmt->result = NULL;
                stmt->state = MYSQLND_STMT_PREPARED;
        }
@@ -356,7 +356,7 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s)
                if (FAIL == (ret = PACKET_READ(fields_eof, stmt->conn))) {
                        if (stmt->result) {
                                stmt->result->m.free_result_contents(stmt->result);
-                               mnd_efree(stmt->result);
+                               mnd_pefree(stmt->result, stmt->result->persistent);
                                memset(stmt, 0, sizeof(MYSQLND_STMT_DATA));
                                stmt->state = MYSQLND_STMT_INITTED;
                        }
diff --git a/ext/pdo_mysql/tests/bug_74376.phpt b/ext/pdo_mysql/tests/bug_74376.phpt
new file mode 100644 (file)
index 0000000..29b1674
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Bug #74376 (Invalid free of persistent results on error/connection loss)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) die('skip not loaded');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+MySQLPDOTest::skip();
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+
+$attr = getenv('PDOTEST_ATTR');
+$attr = $attr ? unserialize($attr) : [];
+$attr[PDO::ATTR_PERSISTENT] = true;
+$attr[PDO::ATTR_EMULATE_PREPARES] = false;
+
+putenv('PDOTEST_ATTR=' . serialize($attr));
+
+$db = MySQLPDOTest::factory();
+$stmt = $db->query("select (select 1 union select 2)");
+
+print "ok";
+?>
+--EXPECTF--
+ok