[php-src] master: Merge branch 'PHP-8.4' into PHP-8.5

From: Date: Wed, 30 Sep 2026 12:45:31 +0000
Subject: [php-src] master: Merge branch 'PHP-8.4' into PHP-8.5
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-141776@lists.php.net to get a copy of this message
Author: Ilia Alshanetsky (iliaal) Date: 2026-09-30T08:21:37-04:00 Commit: https://github.com/php/php-src/commit/be4e9ee71982a821c43810fdcff6e83849299b18 Raw diff: https://github.com/php/php-src/commit/be4e9ee71982a821c43810fdcff6e83849299b18.diff Merge branch 'PHP-8.4' into PHP-8.5 * PHP-8.4: ext/pdo: Drop the previous result when execute() fails Changed paths: A ext/pdo_sqlite/tests/pdo_sqlite_failed_execute.phpt M NEWS M ext/pdo/pdo_stmt.c Diff: diff --git a/NEWS b/NEWS index 80622ec42c41..51c18bf83346 100644 --- a/NEWS +++ b/NEWS @@ -116,6 +116,8 @@ PHP NEWS column index. (Ilia Alshanetsky) . Fixed PDOStatement::bindColumn() registering a binding for a column name that is not in the result set. (Ilia Alshanetsky) + . Fixed PDOStatement::execute() leaving the previous result available + after a failed execution. (Ilia Alshanetsky) . Fixed bug GH-23962 (Destroying a persistent PDO instance rolls back a transaction still in use by another instance). (Lazizbek Ergashev) . Fixed PDO::setAttribute() installing a PDO::ATTR_STATEMENT_CLASS class diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 7192093e8d6b..87f403ba5bf1 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -376,6 +376,29 @@ static bool really_register_bound_param(struct pdo_bound_param_data *param, pdo_ } /* }}} */ +static bool pdo_stmt_do_next_rowset(pdo_stmt_t *stmt); + +static void pdo_stmt_invalidate_result(pdo_stmt_t *stmt) +{ + if (stmt->methods->cursor_closer) { + stmt->methods->cursor_closer(stmt); + } else { + do { + while (stmt->methods->fetcher(stmt, PDO_FETCH_ORI_NEXT, 0)) + ; + if (!stmt->methods->next_rowset) { + break; + } + + if (!pdo_stmt_do_next_rowset(stmt)) { + break; + } + } while (1); + } + + stmt->executed = 0; +} + /* {{{ Execute a prepared statement, optionally binding parameters */ PHP_METHOD(PDOStatement, execute) { @@ -388,6 +411,10 @@ PHP_METHOD(PDOStatement, execute) ZEND_PARSE_PARAMETERS_END(); PHP_STMT_GET_OBJ; + + if (stmt->executed) { + pdo_stmt_invalidate_result(stmt); + } PDO_STMT_CLEAR_ERR(); if (input_params) { diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_failed_execute.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_failed_execute.phpt new file mode 100644 index 000000000000..b711855e2afe --- /dev/null +++ b/ext/pdo_sqlite/tests/pdo_sqlite_failed_execute.phpt @@ -0,0 +1,85 @@ +--TEST-- +PDO SQLite: failed execute invalidates the previous result +--EXTENSIONS-- +pdo_sqlite +--FILE-- +<?php + +$db = new PDO('sqlite::memory:'); + +$stmt = $db->prepare('SELECT ? AS value UNION ALL SELECT 2'); +$stmt->execute(['first']); +var_dump($stmt->fetchColumn()); + +try { + $stmt->execute([new stdClass()]); +} catch (Error $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +var_dump($stmt->fetchColumn()); + +$stmt->execute(['third']); +var_dump($stmt->fetchAll(PDO::FETCH_COLUMN)); + +$db->sqliteCreateFunction('fail_execute', function (bool $fail): string { + if ($fail) { + throw new RuntimeException('execution failed'); + } + return 'first'; +}); +$stmt = $db->prepare('SELECT fail_execute(?) AS value UNION ALL SELECT 2'); +$stmt->execute([false]); +var_dump($stmt->fetchColumn()); + +try { + $stmt->execute([true]); +} catch (RuntimeException $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +var_dump($stmt->fetchColumn()); + +$stmt->execute([false]); +var_dump($stmt->fetchAll(PDO::FETCH_COLUMN)); + +$db->exec('CREATE TABLE failed_execute (value INTEGER UNIQUE)'); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); +$stmt = $db->prepare('INSERT INTO failed_execute VALUES (?)'); +$stmt->execute([1]); +$warnings = 0; +set_error_handler(function () use (&$warnings): bool { + $warnings++; + return true; +}); +try { + var_dump($stmt->execute([1])); +} finally { + restore_error_handler(); +} +echo "driver warnings: $warnings\n"; +var_dump($stmt->fetchColumn()); + +?> +--EXPECTF-- +string(5) "first" +Error: Object of class stdClass could not be converted to string +bool(false) +array(2) { + [0]=> + string(5) "third" + [1]=> + int(2) +} + +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d +string(5) "first" +RuntimeException: execution failed +bool(false) +array(2) { + [0]=> + string(5) "first" + [1]=> + int(2) +} +bool(false) +driver warnings: 1 +bool(false)

« previous php.cvs (#141776) next »