From 3df0f4e5dc751647ca44b94bc95a0bc467767208 Mon Sep 17 00:00:00 2001 From: mehmetcansahin Date: Mon, 25 May 2026 13:31:02 +0300 Subject: [PATCH] Move min/max array fallback into array.c --- UPGRADING.INTERNALS | 2 ++ Zend/zend_hash.c | 67 -------------------------------------------- Zend/zend_hash.h | 1 - ext/standard/array.c | 22 ++++++++++++--- 4 files changed, 20 insertions(+), 72 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index c340ba64833c..9069de7d4de6 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -35,6 +35,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 2913af9c2b5f..acc342bc267d 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 6a695aeef449..9f9919c568c2 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 25259c47d61b..8c553c2fe4af 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_argument_type_error(1, "must be of type array, %s given", zend_zval_value_name(&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_argument_type_error(1, "must be of type array, %s given", zend_zval_value_name(&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 {