Commit 9060fd33665 for php.net

commit 9060fd336657b93986e5934d5abb380a6bc19eb3
Author: mehmetcan <2010841+mehmetcansahin@users.noreply.github.com>
Date:   Mon Jun 29 19:43:29 2026 +0300

    Move min/max array fallback into array.c (#22147)

diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index a467df3b6be..a8eb6b80541 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -36,6 +36,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES
   . The zval_dtor() alias of zval_ptr_dtor_nogc() has been removed.
     Call zval_ptr_dtor_nogc() directly instead.
   . The internal zend_copy_parameters_array() function is no longer exposed.
+  . The internal zend_hash_minmax() function is no longer exposed. Scan the
+    HashTable directly and use zend_compare() for value comparisons instead.
   . The zend_make_callable() function has been removed, if a callable zval
     needs to be obtained use the zend_get_callable_zval_from_fcc() function
     instead. If this was used to store a callable, then an FCC should be
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 2913af9c2b5..acc342bc267 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -3238,73 +3238,6 @@ ZEND_API int zend_hash_compare(HashTable *ht1, const HashTable *ht2, compare_fun
 }


-ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag)
-{
-	uint32_t idx;
-	zval *res;
-
-	IS_CONSISTENT(ht);
-
-	if (ht->nNumOfElements == 0 ) {
-		return NULL;
-	}
-
-	if (HT_IS_PACKED(ht)) {
-		zval *zv;
-
-		idx = 0;
-		while (1) {
-			if (idx == ht->nNumUsed) {
-				return NULL;
-			}
-			if (Z_TYPE(ht->arPacked[idx]) != IS_UNDEF) break;
-			idx++;
-		}
-		res = ht->arPacked + idx;
-		for (; idx < ht->nNumUsed; idx++) {
-			zv = ht->arPacked + idx;
-			if (UNEXPECTED(Z_TYPE_P(zv) == IS_UNDEF)) continue;
-
-			if (flag) {
-				if (compar(res, zv) < 0) { /* max */
-					res = zv;
-				}
-			} else {
-				if (compar(res, zv) > 0) { /* min */
-					res = zv;
-				}
-			}
-		}
-	} else {
-		Bucket *p;
-
-		idx = 0;
-		while (1) {
-			if (idx == ht->nNumUsed) {
-				return NULL;
-			}
-			if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
-			idx++;
-		}
-		res = &ht->arData[idx].val;
-		for (; idx < ht->nNumUsed; idx++) {
-			p = ht->arData + idx;
-			if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
-
-			if (flag) {
-				if (compar(res, &p->val) < 0) { /* max */
-					res = &p->val;
-				}
-			} else {
-				if (compar(res, &p->val) > 0) { /* min */
-					res = &p->val;
-				}
-			}
-		}
-	}
-	return res;
-}
-
 ZEND_API bool ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
 {
 	const char *tmp = key;
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 6c0d4a241a1..1181bee29fa 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -303,7 +303,6 @@ typedef int (*bucket_compare_func_t)(Bucket *a, Bucket *b);
 ZEND_API int   zend_hash_compare(HashTable *ht1, const HashTable *ht2, compare_func_t compar, bool ordered);
 ZEND_API void  ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber);
 ZEND_API void  ZEND_FASTCALL zend_array_sort_ex(HashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber);
-ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag);

 static zend_always_inline void ZEND_FASTCALL zend_hash_sort(HashTable *ht, bucket_compare_func_t compare_func, bool renumber) {
 	zend_hash_sort_ex(ht, zend_sort, compare_func, renumber);
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 3b17ca3f794..a233e6c4dcb 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1089,9 +1089,23 @@ PHP_FUNCTION(key)
 }
 /* }}} */

-static int php_data_compare(const void *f, const void *s) /* {{{ */
+static zval *php_array_data_minmax(HashTable *array, bool max) /* {{{ */
 {
-	return zend_compare((zval*)f, (zval*)s);
+	zval *entry, *result = NULL;
+
+	ZEND_HASH_FOREACH_VAL(array, entry) {
+		if (!result) {
+			result = entry;
+			continue;
+		}
+
+		int cmp = zend_compare(result, entry);
+		if (max ? cmp < 0 : cmp > 0) {
+			result = entry;
+		}
+	} ZEND_HASH_FOREACH_END();
+
+	return result;
 }
 /* }}} */

@@ -1114,7 +1128,7 @@ PHP_FUNCTION(min)
 			zend_wrong_parameter_type_error(1, Z_EXPECTED_ARRAY, &args[0]);
 			RETURN_THROWS();
 		} else {
-			zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_data_compare, 0);
+			zval *result = php_array_data_minmax(Z_ARRVAL(args[0]), false);
 			if (result) {
 				RETURN_COPY_DEREF(result);
 			} else {
@@ -1242,7 +1256,7 @@ PHP_FUNCTION(max)
 			zend_wrong_parameter_type_error(1, Z_EXPECTED_ARRAY, &args[0]);
 			RETURN_THROWS();
 		} else {
-			zval *result = zend_hash_minmax(Z_ARRVAL(args[0]), php_data_compare, 1);
+			zval *result = php_array_data_minmax(Z_ARRVAL(args[0]), true);
 			if (result) {
 				RETURN_COPY_DEREF(result);
 			} else {