From: Keyur Date: Mon, 8 Aug 2016 23:34:00 +0000 (+0000) Subject: Fix bug 72788: Invalid memory access when database_object_handle X-Git-Tag: php-7.1.0beta3~86^2~1^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f25c4228a8f505a000c1ea5751062606247349a;p=php Fix bug 72788: Invalid memory access when database_object_handle is undefined. Also fix memory leak in dbh_free when using persistent PDO connections. --- diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 2fb5334a9d..8a7c1d3931 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 0000000000..80609a21ba --- /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 31ee88b76b..2b8568fb46 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 b141de79ef..4a2146dd16 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 219678c671..4c11453637 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 a5ee2e993e..f7c46a6706 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) {