Commit 6d95a2238d5 for php.net

commit 6d95a2238d5f3305d2e5ae05c19288cbb6753596
Author: Jorg Adam Sowa <jorg.sowa@gmail.com>
Date:   Mon Jan 26 17:02:15 2026 +0100

    ext/standard: validate mode in array_filter() (#15647)

    And add the missing ARRAY_FILTER_USE_VALUE for the default case.

diff --git a/NEWS b/NEWS
index 86a2174a986..bf00d8f663b 100644
--- a/NEWS
+++ b/NEWS
@@ -99,6 +99,8 @@ PHP                                                                        NEWS
 - Standard:
   . Fixed bug GH-19926 (reset internal pointer earlier while splicing array
     while COW violation flag is still set). (alexandre-daubois)
+  . Invalid mode values now throw in array_filter() instead of being silently
+    defaulted to 0. (Jorg Sowa)

 - Streams:
   . Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream
diff --git a/UPGRADING b/UPGRADING
index 0d24268b787..fec4b15c102 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -23,6 +23,10 @@ PHP 8.6 UPGRADE NOTES
   . Invalid values now throw in Phar::mungServer() instead of being silently
     ignored.

+- Standard:
+  . Invalid mode values now throw in array_filter() instead of being silently
+    defaulted to 0.
+
 ========================================
 2. New Features
 ========================================
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 893e07dd8f9..f8dd7d891dd 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -6453,7 +6453,7 @@ PHP_FUNCTION(array_filter)
 	zval args[2];
 	zval retval;
 	bool have_callback = 0;
-	zend_long use_type = 0;
+	zend_long use_type = ARRAY_FILTER_USE_VALUE;
 	zend_string *string_key;
 	zend_fcall_info fci = empty_fcall_info;
 	zend_fcall_info_cache fci_cache;
@@ -6466,6 +6466,16 @@ PHP_FUNCTION(array_filter)
 		Z_PARAM_LONG(use_type)
 	ZEND_PARSE_PARAMETERS_END();

+	switch (use_type) {
+		case ARRAY_FILTER_USE_VALUE:
+		case ARRAY_FILTER_USE_BOTH:
+		case ARRAY_FILTER_USE_KEY:
+			break;
+		default:
+			zend_argument_value_error(3, "must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH");
+		RETURN_THROWS();
+	}
+
 	if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
 		RETVAL_EMPTY_ARRAY();
 		return;
@@ -6486,7 +6496,7 @@ PHP_FUNCTION(array_filter)

 	ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_key, string_key, operand) {
 		if (have_callback) {
-			if (use_type) {
+			if (use_type != ARRAY_FILTER_USE_VALUE) {
 				/* Set up the key */
 				if (!string_key) {
 					ZVAL_LONG(key, num_key);
diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php
index e27dca069c5..4ad26063a67 100644
--- a/ext/standard/basic_functions.stub.php
+++ b/ext/standard/basic_functions.stub.php
@@ -109,6 +109,11 @@
  */
 const COUNT_RECURSIVE = UNKNOWN;

+/**
+ * @var int
+ * @cvalue ARRAY_FILTER_USE_VALUE
+ */
+const ARRAY_FILTER_USE_VALUE = UNKNOWN;
 /**
  * @var int
  * @cvalue ARRAY_FILTER_USE_BOTH
diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h
index 9f5d89991da..2a1aa634fcd 100644
Binary files a/ext/standard/basic_functions_arginfo.h and b/ext/standard/basic_functions_arginfo.h differ
diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h
index 2a35af60380..2205082e91d 100644
--- a/ext/standard/php_array.h
+++ b/ext/standard/php_array.h
@@ -59,6 +59,7 @@ PHPAPI bool php_array_pick_keys(php_random_algo_with_state engine, zval *input,
 #define PHP_COUNT_NORMAL      0
 #define PHP_COUNT_RECURSIVE   1

+#define ARRAY_FILTER_USE_VALUE	0
 #define ARRAY_FILTER_USE_BOTH	1
 #define ARRAY_FILTER_USE_KEY	2

diff --git a/ext/standard/tests/array/array_filter_invalid_mode.phpt b/ext/standard/tests/array/array_filter_invalid_mode.phpt
new file mode 100644
index 00000000000..b312bcfe5a2
--- /dev/null
+++ b/ext/standard/tests/array/array_filter_invalid_mode.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Test array_filter() function : usage variations - mode exception
+--FILE--
+<?php
+
+try {
+    var_dump(array_filter([], mode: 999));
+} catch (Throwable $e) {
+    echo $e::class . ': '.$e->getMessage(), "\n";
+}
+
+echo "Done"
+?>
+--EXPECT--
+ValueError: array_filter(): Argument #3 ($mode) must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH
+Done