From 3f25c4228a8f505a000c1ea5751062606247349a Mon Sep 17 00:00:00 2001 From: Keyur Date: Mon, 8 Aug 2016 23:34:00 +0000 Subject: [PATCH 1/3] Fix bug 72788: Invalid memory access when database_object_handle is undefined. Also fix memory leak in dbh_free when using persistent PDO connections. --- ext/pdo/pdo_dbh.c | 8 ++--- ext/pdo/tests/bug_72788.phpt | 33 +++++++++++++++++++ ext/pdo/tests/pdo_017.phpt | 4 +-- ext/pdo_mysql/mysql_statement.c | 3 +- .../tests/pdo_mysql___construct.phpt | 1 + ext/pdo_pgsql/pgsql_statement.c | 3 +- 6 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 ext/pdo/tests/bug_72788.phpt diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 2fb5334a9d3..8a7c1d39318 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1503,15 +1503,15 @@ static void dbh_free(pdo_dbh_t *dbh, zend_bool free_persistent) { int i; - if (dbh->is_persistent && !free_persistent) { - return; - } - if (dbh->query_stmt) { zval_ptr_dtor(&dbh->query_stmt_zval); dbh->query_stmt = NULL; } + if (dbh->is_persistent && !free_persistent) { + return; + } + if (dbh->methods) { dbh->methods->closer(dbh); } diff --git a/ext/pdo/tests/bug_72788.phpt b/ext/pdo/tests/bug_72788.phpt new file mode 100644 index 00000000000..80609a21ba2 --- /dev/null +++ b/ext/pdo/tests/bug_72788.phpt @@ -0,0 +1,33 @@ +--TEST-- +PDO Common: Bug #72788 (Invalid memory access when using persistent PDO connection) +--SKIPIF-- + +--FILE-- + true))); + +function test() { + $db = PDOTest::factory('PDO', false); + $stmt = @$db->query("SELECT 1 FROM TABLE_DOES_NOT_EXIST"); + if ($stmt === false) { + echo "Statement failed as expected\n"; + } +} + +test(); +test(); +echo "Done"; +?> +--EXPECT-- +Statement failed as expected +Statement failed as expected +Done diff --git a/ext/pdo/tests/pdo_017.phpt b/ext/pdo/tests/pdo_017.phpt index 31ee88b76b4..2b8568fb46c 100644 --- a/ext/pdo/tests/pdo_017.phpt +++ b/ext/pdo/tests/pdo_017.phpt @@ -16,7 +16,7 @@ try { } if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { - require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . '../../pdo_mysql/tests/mysql_pdo_test.inc'); if (false === MySQLPDOTest::detect_transactional_mysql_engine($db)) { die('skip your mysql configuration does not support working transactions'); } @@ -29,7 +29,7 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { - require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . '../../pdo_mysql/tests/mysql_pdo_test.inc'); $suf = ' ENGINE=' . MySQLPDOTest::detect_transactional_mysql_engine($db); } else { $suf = ''; diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c index b141de79efe..4a2146dd161 100644 --- a/ext/pdo_mysql/mysql_statement.c +++ b/ext/pdo_mysql/mysql_statement.c @@ -88,7 +88,8 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */ } #endif - if (IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)]) + if (!Z_ISUNDEF(stmt->database_object_handle) + && IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)]) && (!(GC_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED))) { while (mysql_more_results(S->H->server)) { MYSQL_RES *res; diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt index 219678c671a..4c11453637a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt @@ -300,5 +300,6 @@ MySQLPDOTest::skip(); [006] invalid data source name, [n/a] n/a [007] could not find driver, [n/a] n/a [009] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a +[015] DSN=%s, SQLSTATE[%s] [%d] %s [017] DSN=%s, SQLSTATE[%s] [%d] %s done! diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index a5ee2e993e8..f7c46a67068 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -61,7 +61,8 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; - zend_bool server_obj_usable = IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)]) + zend_bool server_obj_usable = !Z_ISUNDEF(stmt->database_object_handle) + && IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)]) && !(GC_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED); if (S->result) { From a74c7cb528c47726ee998a514986663a9c6835e5 Mon Sep 17 00:00:00 2001 From: Keyur Date: Tue, 9 Aug 2016 01:36:15 +0000 Subject: [PATCH 2/3] Remove typo'd commit --- ext/pdo_mysql/tests/pdo_mysql___construct.phpt | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt index 4c11453637a..219678c671a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt @@ -300,6 +300,5 @@ MySQLPDOTest::skip(); [006] invalid data source name, [n/a] n/a [007] could not find driver, [n/a] n/a [009] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a -[015] DSN=%s, SQLSTATE[%s] [%d] %s [017] DSN=%s, SQLSTATE[%s] [%d] %s done! From e52cb1858d70251812d76c49f526019d487aa762 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 9 Aug 2016 11:32:16 +0800 Subject: [PATCH 3/3] Fixed bug #72788 (Invalid memory access when using persistent PDO connection) --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 0d4ac3a20d1..8925cf82872 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ PHP NEWS . Fixed invalid handle error with Implicit Result Sets. (Chris Jones) . Fixed bug #72524 (Binding null values triggers ORA-24816 error). (Chris Jones) +- PDO: + . Fixed bug #72788 (Invalid memory access when using persistent PDO + connection). (Keyur) + - Session: . Fixed bug #72724 (PHP7: session-uploadprogress kills httpd). (Nikita)