Commit d8d55b75c5d for php

commit d8d55b75c5dd3342ae6762113847c3f6b986f172
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Tue Oct 13 08:32:11 2026 -0400

    ext/pdo: Report $options as the argument for constructor option errors

    An attribute in the $options array of PDO::__construct() or PDO::connect()
    that fails validation was reported against argument #3 ($password) instead
    of argument #4 ($options), because php_pdo_internal_construct_driver()
    passed a value_arg_num of 3 to pdo_dbh_attribute_set().

    Closes GH-24297

diff --git a/NEWS b/NEWS
index d589da31754..07e265d2193 100644
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,8 @@ PHP                                                                        NEWS
 - PDO:
   . Fixed a duplicate warning when ATTR_STATEMENT_CLASS is rejected on a
     persistent connection. (Ilia Alshanetsky)
+  . Fixed constructor option errors naming argument #3 ($password) instead
+    of argument #4 ($options). (Ilia Alshanetsky)

 - Phpdbg:
   . Fix wrong command names. (ndossche, Weilin Du)
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index f5a16f20aef..fcb1ff4498a 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -516,7 +516,7 @@ PDO_API void php_pdo_internal_construct_driver(INTERNAL_FUNCTION_PARAMETERS, zen
 				ZVAL_DEREF(attr_value);

 				/* TODO: Should the constructor fail when the attribute cannot be set? */
-				pdo_dbh_attribute_set(dbh, long_key, attr_value, 3);
+				pdo_dbh_attribute_set(dbh, long_key, attr_value, 4);
 			} ZEND_HASH_FOREACH_END();
 		}

diff --git a/ext/pdo/tests/pdo_constructor_option_argnum.phpt b/ext/pdo/tests/pdo_constructor_option_argnum.phpt
new file mode 100644
index 00000000000..5aebe0b4a2a
--- /dev/null
+++ b/ext/pdo/tests/pdo_constructor_option_argnum.phpt
@@ -0,0 +1,38 @@
+--TEST--
+PDO Common: Constructor option errors report $options as argument #4
+--EXTENSIONS--
+pdo
+--SKIPIF--
+<?php
+$dir = getenv('REDIR_TEST_DIR');
+if (false == $dir) die('skip no driver');
+require_once $dir . 'pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
+require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
+
+foreach ([false, true] as $useConnectMethod) {
+    foreach ([[PDO::ATTR_ERRMODE => 999], [PDO::ATTR_STATEMENT_CLASS => 'PDOStatement']] as $options) {
+        putenv("PDOTEST_ATTR=" . serialize($options));
+        try {
+            PDOTest::factory(PDO::class, $useConnectMethod);
+        } catch (Error $e) {
+            echo $e::class, ": ", $e->getMessage(), "\n";
+        }
+    }
+
+    putenv("PDOTEST_ATTR=" . serialize([PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_NUM]));
+    $db = PDOTest::factory(PDO::class, $useConnectMethod);
+    var_dump($db->getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE) === PDO::FETCH_NUM);
+}
+?>
+--EXPECT--
+ValueError: PDO::__construct(): Argument #4 ($options) Error mode must be one of the PDO::ERRMODE_* constants
+TypeError: PDO::__construct(): Argument #4 ($options) PDO::ATTR_STATEMENT_CLASS value must be of type array, string given
+bool(true)
+ValueError: PDO::connect(): Argument #4 ($options) Error mode must be one of the PDO::ERRMODE_* constants
+TypeError: PDO::connect(): Argument #4 ($options) PDO::ATTR_STATEMENT_CLASS value must be of type array, string given
+bool(true)