summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2017-04-07 15:20:53 +0800
committerXinchen Hui <laruence@gmail.com>2017-04-07 15:20:53 +0800
commit39327b90e3eef1128c757e0970c4c9935c83f889 (patch)
tree12ef39ada3d08c229128fe45c4ac4ae46e453f16
parentadc49b1d18788cb8497eb176d4ac147f144f79bf (diff)
parent27120d4412a7122f27ac1fcd4d91090ce7979647 (diff)
downloadphp-git-39327b90e3eef1128c757e0970c4c9935c83f889.tar.gz
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0: Fix invalid free of persistent results on error/connection loss in mysqlnd (bug 74376) Conflicts: ext/mysqlnd/mysqlnd_ps.c
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c4
-rw-r--r--ext/pdo_mysql/tests/bug_74376.phpt27
2 files changed, 29 insertions, 2 deletions
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 256bbe4d47..41c024ab16 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -122,7 +122,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;
}
@@ -347,7 +347,7 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s)
if (FAIL == (ret = PACKET_READ(fields_eof))) {
if (stmt->result) {
stmt->result->m.free_result_contents(stmt->result);
- mnd_efree(stmt->result);
+ mnd_pefree(stmt->result, stmt->result->persistent);
/* XXX: This will crash, because we will null also the methods.
But seems it happens in extreme cases or doesn't. Should be fixed by exporting a function
(from mysqlnd_driver.c?) to do the reset.
diff --git a/ext/pdo_mysql/tests/bug_74376.phpt b/ext/pdo_mysql/tests/bug_74376.phpt
new file mode 100644
index 0000000000..29b16748ff
--- /dev/null
+++ b/ext/pdo_mysql/tests/bug_74376.phpt
@@ -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