Commit 4843327a90b for php.net

commit 4843327a90b01ed3aef3b9c30b4088f38ea780e4
Author: David Carlier <devnexen@gmail.com>
Date:   Mon Apr 6 20:53:19 2026 +0100

    ext/standard: pathinfo() check flags argument validity.

    close GH-17859

diff --git a/NEWS b/NEWS
index f22f5b47017..d688ef5aad3 100644
--- a/NEWS
+++ b/NEWS
@@ -146,6 +146,8 @@ PHP                                                                        NEWS
     (ndossche)
   . Add array size maximum to array_diff(). (ndossche)
   . Add enum SortDirection. (timwolla)
+  . pathinfo() raises a ValueError with an invalid $flags argument.
+    (David Carlier)

 - Streams:
   . Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream
diff --git a/UPGRADING b/UPGRADING
index 18f34eca198..a97ad00061a 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -131,6 +131,10 @@ PHP 8.6 UPGRADE NOTES
     when not null, and on failure, gives the error code (one of the EAI_*
     constants).

+- Standard:
+  . pathinfo() now raises a ValueError when an invalid $flag argument
+    value is passed.
+
 - Zip:
   . ZipArchive::extractTo now raises a TypeError for the
     files argument if one or more of the entries is not
diff --git a/ext/standard/string.c b/ext/standard/string.c
index e479a9e7612..d7f76af633c 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -1591,6 +1591,16 @@ PHP_FUNCTION(pathinfo)
 		Z_PARAM_LONG(opt)
 	ZEND_PARSE_PARAMETERS_END();

+	if (opt < PHP_PATHINFO_DIRNAME || opt > PHP_PATHINFO_ALL) {
+		zend_argument_value_error(2, "must be one of the PATHINFO_* constants");
+		RETURN_THROWS();
+	}
+
+	if (opt < PHP_PATHINFO_ALL && (opt & (opt - 1))) {
+		zend_argument_value_error(2, "must be only one of the PATHINFO_* constants");
+		RETURN_THROWS();
+	}
+
 	have_basename = (opt & PHP_PATHINFO_BASENAME);

 	array_init(&tmp);
diff --git a/ext/standard/tests/file/pathinfo_variation3.phpt b/ext/standard/tests/file/pathinfo_variation3.phpt
index aa1494b5799..86f88677d81 100644
--- a/ext/standard/tests/file/pathinfo_variation3.phpt
+++ b/ext/standard/tests/file/pathinfo_variation3.phpt
@@ -15,15 +15,37 @@
 var_dump(pathinfo($testfile, PATHINFO_FILENAME));
 var_dump(pathinfo($testfile, PATHINFO_EXTENSION));
 var_dump(pathinfo($testfile, PATHINFO_DIRNAME));
-var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME));
-var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_BASENAME));
-var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME));
-var_dump(pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_BASENAME));
-var_dump(pathinfo($testfile, PATHINFO_FILENAME|PATHINFO_DIRNAME));
-var_dump(pathinfo($testfile, PATHINFO_FILENAME|PATHINFO_BASENAME));
-var_dump(pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_EXTENSION));
-var_dump(pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_BASENAME));

+try {
+	pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_FILENAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo($testfile, PATHINFO_EXTENSION|PATHINFO_DIRNAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo($testfile, PATHINFO_FILENAME|PATHINFO_BASENAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_EXTENSION);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo($testfile, PATHINFO_DIRNAME|PATHINFO_BASENAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}

 ?>
 --EXPECTF--
@@ -62,11 +84,9 @@
 string(4) "inet"
 string(1) "h"
 string(17) "/usr/include/arpa"
-string(17) "/usr/include/arpa"
-string(6) "inet.h"
-string(1) "h"
-string(6) "inet.h"
-string(17) "/usr/include/arpa"
-string(6) "inet.h"
-string(17) "/usr/include/arpa"
-string(17) "/usr/include/arpa"
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
diff --git a/ext/standard/tests/strings/pathinfo.phpt b/ext/standard/tests/strings/pathinfo.phpt
index 2bbea73588c..1ff42a66121 100644
--- a/ext/standard/tests/strings/pathinfo.phpt
+++ b/ext/standard/tests/strings/pathinfo.phpt
@@ -14,14 +14,48 @@
 var_dump(pathinfo(__FILE__, PATHINFO_FILENAME));
 var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION));
 var_dump(pathinfo(__FILE__, PATHINFO_DIRNAME));
-var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME));
-var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_BASENAME));
-var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME));
-var_dump(pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_BASENAME));
-var_dump(pathinfo(__FILE__, PATHINFO_FILENAME|PATHINFO_DIRNAME));
-var_dump(pathinfo(__FILE__, PATHINFO_FILENAME|PATHINFO_BASENAME));
-var_dump(pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_EXTENSION));
-var_dump(pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_BASENAME));
+
+try {
+	pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME|PATHINFO_DIRNAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_FILENAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo(__FILE__, PATHINFO_EXTENSION|PATHINFO_DIRNAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo(__FILE__, PATHINFO_FILENAME|PATHINFO_BASENAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_EXTENSION);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo(__FILE__, PATHINFO_DIRNAME|PATHINFO_BASENAME);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+
+try {
+	pathinfo(__FILE__, PATHINFO_DIRNAME-1);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}
+try {
+	pathinfo(__FILE__, PATHINFO_ALL+1);
+} catch (\ValueError $e) {
+	echo $e->getMessage(), PHP_EOL;
+}

 echo "Done\n";
 ?>
@@ -94,12 +128,12 @@
 string(8) "pathinfo"
 string(3) "php"
 string(%d) "%s%estrings"
-string(%d) "%s%estrings"
-string(12) "pathinfo.php"
-string(3) "php"
-string(12) "pathinfo.php"
-string(%d) "%s%estrings"
-string(12) "pathinfo.php"
-string(%d) "%s%estrings"
-string(%d) "%s%estrings"
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be one of the PATHINFO_* constants
+pathinfo(): Argument #2 ($flags) must be one of the PATHINFO_* constants
 Done