Commit 38cbbee4aa1 for php.net
commit 38cbbee4aa14d2832686eeb771b9e8fa1539aa4e
Author: Gina Peter Banyard <girgias@php.net>
Date: Thu Mar 19 20:36:19 2026 +0000
Zend: add const qualifiers to the majority of compare functions (#21304)
This sadly does not include zend_compare() and functions relying on it because the default compare object hook (zend_std_compare_objects()) relies on zend_compare(), and adds recursion protections to OP1.
Thus making it seems difficult or even impossible for zend_compare to take const parameters.
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index e0e789cb7cb..959becb5747 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -3209,7 +3209,7 @@ static zend_always_inline int zend_hash_compare_impl(const HashTable *ht1, const
return 0;
}
-ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered)
+ZEND_API int zend_hash_compare(HashTable *ht1, const HashTable *ht2, compare_func_t compar, bool ordered)
{
int result;
IS_CONSISTENT(ht1);
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 70d9721cb7a..6d6c29b5e6b 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -301,7 +301,7 @@ ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q);
ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q);
typedef int (*bucket_compare_func_t)(Bucket *a, Bucket *b);
-ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered);
+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);
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 571494088e3..58624ea5e1c 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1059,7 +1059,7 @@ ZEND_API double ZEND_FASTCALL zval_get_double_func(const zval *op) /* {{{ */
}
/* }}} */
-static zend_always_inline zend_string* __zval_get_string_func(zval *op, bool try) /* {{{ */
+static zend_always_inline zend_string* __zval_get_string_func(const zval *op, bool try) /* {{{ */
{
try_again:
switch (Z_TYPE_P(op)) {
@@ -1100,19 +1100,19 @@ static zend_always_inline zend_string* __zval_get_string_func(zval *op, bool try
}
/* }}} */
-ZEND_API zend_string* ZEND_FASTCALL zval_get_string_func(zval *op) /* {{{ */
+ZEND_API zend_string* ZEND_FASTCALL zval_get_string_func(const zval *op) /* {{{ */
{
return __zval_get_string_func(op, false);
}
/* }}} */
-ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(zval *op) /* {{{ */
+ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(const zval *op) /* {{{ */
{
return __zval_get_string_func(op, true);
}
/* }}} */
-static ZEND_COLD zend_never_inline void ZEND_FASTCALL zend_binop_error(const char *operator, zval *op1, zval *op2) /* {{{ */ {
+static ZEND_COLD zend_never_inline void ZEND_FASTCALL zend_binop_error(const char *operator, const zval *op1, const zval *op2) /* {{{ */ {
if (EG(exception)) {
return;
}
@@ -1122,7 +1122,7 @@ static ZEND_COLD zend_never_inline void ZEND_FASTCALL zend_binop_error(const cha
}
/* }}} */
-static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zval *op1, zval *op2) /* {{{ */
+static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
if (result == op1 && Z_ARR_P(op1) == Z_ARR_P(op2)) {
/* $a += $a */
@@ -2159,7 +2159,7 @@ has_op2_string:;
}
/* }}} */
-ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, bool case_insensitive) /* {{{ */
+ZEND_API int ZEND_FASTCALL string_compare_function_ex(const zval *op1, const zval *op2, bool case_insensitive) /* {{{ */
{
zend_string *tmp_str1, *tmp_str2;
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
@@ -2178,7 +2178,7 @@ ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, bool
}
/* }}} */
-ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2) /* {{{ */
+ZEND_API int ZEND_FASTCALL string_compare_function(const zval *op1, const zval *op2) /* {{{ */
{
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
@@ -2200,7 +2200,7 @@ ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2) /* {{{
}
/* }}} */
-ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2) /* {{{ */
+ZEND_API int ZEND_FASTCALL string_case_compare_function(const zval *op1, const zval *op2) /* {{{ */
{
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
@@ -2222,7 +2222,7 @@ ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2) /*
}
/* }}} */
-ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2) /* {{{ */
+ZEND_API int ZEND_FASTCALL string_locale_compare_function(const zval *op1, const zval *op2) /* {{{ */
{
zend_string *tmp_str1, *tmp_str2;
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
@@ -2235,7 +2235,7 @@ ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2)
}
/* }}} */
-ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2) /* {{{ */
+ZEND_API int ZEND_FASTCALL numeric_compare_function(const zval *op1, const zval *op2) /* {{{ */
{
double d1, d2;
@@ -2253,7 +2253,7 @@ ZEND_API zend_result ZEND_FASTCALL compare_function(zval *result, zval *op1, zva
}
/* }}} */
-static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
+static int compare_long_to_string(zend_long lval, const zend_string *str) /* {{{ */
{
zend_long str_lval;
double str_dval;
@@ -2275,7 +2275,7 @@ static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
}
/* }}} */
-static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
+static int compare_double_to_string(double dval, const zend_string *str) /* {{{ */
{
zend_long str_lval;
double str_dval;
@@ -2459,7 +2459,7 @@ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */
/* }}} */
/* return int to be compatible with compare_func_t */
-static int hash_zval_identical_function(zval *z1, zval *z2) /* {{{ */
+static int hash_zval_identical_function(const zval *z1, const zval *z2) /* {{{ */
{
/* is_identical_function() returns 1 in case of identity and 0 in case
* of a difference;
@@ -2501,14 +2501,14 @@ ZEND_API bool ZEND_FASTCALL zend_is_identical(const zval *op1, const zval *op2)
}
/* }}} */
-ZEND_API zend_result ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
+ZEND_API zend_result ZEND_FASTCALL is_identical_function(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
ZVAL_BOOL(result, zend_is_identical(op1, op2));
return SUCCESS;
}
/* }}} */
-ZEND_API zend_result ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
+ZEND_API zend_result ZEND_FASTCALL is_not_identical_function(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
ZVAL_BOOL(result, !zend_is_identical(op1, op2));
return SUCCESS;
@@ -3354,19 +3354,19 @@ ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1
}
/* }}} */
-ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
+ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(const zval *s1, const zval *s2) /* {{{ */
{
return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
}
/* }}} */
-ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
+ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(const zval *s1, const zval *s2, const zval *s3) /* {{{ */
{
return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
}
/* }}} */
-ZEND_API bool ZEND_FASTCALL zendi_smart_streq(zend_string *s1, zend_string *s2) /* {{{ */
+ZEND_API bool ZEND_FASTCALL zendi_smart_streq(const zend_string *s1, const zend_string *s2) /* {{{ */
{
uint8_t ret1, ret2;
int oflow1, oflow2;
@@ -3414,7 +3414,7 @@ ZEND_API bool ZEND_FASTCALL zendi_smart_streq(zend_string *s1, zend_string *s2)
}
/* }}} */
-ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2) /* {{{ */
+ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(const zend_string *s1, const zend_string *s2) /* {{{ */
{
uint8_t ret1, ret2;
int oflow1, oflow2;
@@ -3489,7 +3489,7 @@ ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable
}
/* }}} */
-ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2) /* {{{ */
+ZEND_API int ZEND_FASTCALL zend_compare_arrays(const zval *a1, const zval *a2) /* {{{ */
{
return zend_compare_symbol_tables(Z_ARRVAL_P(a1), Z_ARRVAL_P(a2));
}
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index e6d648d1208..408b2eee65c 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -71,8 +71,8 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
ZEND_API bool ZEND_FASTCALL zend_is_identical(const zval *op1, const zval *op2);
ZEND_API zend_result ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2);
-ZEND_API zend_result ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2);
-ZEND_API zend_result ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zval *op2);
+ZEND_API zend_result ZEND_FASTCALL is_identical_function(zval *result, const zval *op1, const zval *op2);
+ZEND_API zend_result ZEND_FASTCALL is_not_identical_function(zval *result, const zval *op1, const zval *op2);
ZEND_API zend_result ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2);
ZEND_API zend_result ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2);
ZEND_API zend_result ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2);
@@ -325,8 +325,8 @@ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op);
ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_strict);
ZEND_API zend_long ZEND_FASTCALL zval_try_get_long(const zval *op, bool *failed);
ZEND_API double ZEND_FASTCALL zval_get_double_func(const zval *op);
-ZEND_API zend_string* ZEND_FASTCALL zval_get_string_func(zval *op);
-ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(zval *op);
+ZEND_API zend_string* ZEND_FASTCALL zval_get_string_func(const zval *op);
+ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(const zval *op);
static zend_always_inline zend_long zval_get_long(const zval *op) {
return EXPECTED(Z_TYPE_P(op) == IS_LONG) ? Z_LVAL_P(op) : zval_get_long_func(op, false);
@@ -337,11 +337,11 @@ static zend_always_inline zend_long zval_get_long_ex(const zval *op, bool is_str
static zend_always_inline double zval_get_double(const zval *op) {
return EXPECTED(Z_TYPE_P(op) == IS_DOUBLE) ? Z_DVAL_P(op) : zval_get_double_func(op);
}
-static zend_always_inline zend_string *zval_get_string(zval *op) {
+static zend_always_inline zend_string *zval_get_string(const zval *op) {
return EXPECTED(Z_TYPE_P(op) == IS_STRING) ? zend_string_copy(Z_STR_P(op)) : zval_get_string_func(op);
}
-static zend_always_inline zend_string *zval_get_tmp_string(zval *op, zend_string **tmp) {
+static zend_always_inline zend_string *zval_get_tmp_string(const zval *op, zend_string **tmp) {
if (EXPECTED(Z_TYPE_P(op) == IS_STRING)) {
*tmp = NULL;
return Z_STR_P(op);
@@ -356,7 +356,7 @@ static zend_always_inline void zend_tmp_string_release(zend_string *tmp) {
}
/* Like zval_get_string, but returns NULL if the conversion fails with an exception. */
-static zend_always_inline zend_string *zval_try_get_string(zval *op) {
+static zend_always_inline zend_string *zval_try_get_string(const zval *op) {
if (EXPECTED(Z_TYPE_P(op) == IS_STRING)) {
zend_string *ret = zend_string_copy(Z_STR_P(op));
ZEND_ASSUME(ret != NULL);
@@ -367,7 +367,7 @@ static zend_always_inline zend_string *zval_try_get_string(zval *op) {
}
/* Like zval_get_tmp_string, but returns NULL if the conversion fails with an exception. */
-static zend_always_inline zend_string *zval_try_get_tmp_string(zval *op, zend_string **tmp) {
+static zend_always_inline zend_string *zval_try_get_tmp_string(const zval *op, zend_string **tmp) {
if (EXPECTED(Z_TYPE_P(op) == IS_STRING)) {
zend_string *ret = Z_STR_P(op);
*tmp = NULL;
@@ -458,11 +458,11 @@ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2);
ZEND_API zend_result ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2);
-ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2);
-ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, bool case_insensitive);
-ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2);
-ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2);
-ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2);
+ZEND_API int ZEND_FASTCALL numeric_compare_function(const zval *op1, const zval *op2);
+ZEND_API int ZEND_FASTCALL string_compare_function_ex(const zval *op1, const zval *op2, bool case_insensitive);
+ZEND_API int ZEND_FASTCALL string_compare_function(const zval *op1, const zval *op2);
+ZEND_API int ZEND_FASTCALL string_case_compare_function(const zval *op1, const zval *op2);
+ZEND_API int ZEND_FASTCALL string_locale_compare_function(const zval *op1, const zval *op2);
ZEND_API extern const unsigned char zend_tolower_map[256];
ZEND_API extern const unsigned char zend_toupper_map[256];
@@ -488,8 +488,8 @@ static zend_always_inline zend_string* zend_string_toupper(zend_string *str) {
return zend_string_toupper_ex(str, false);
}
-ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2);
-ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
+ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(const zval *s1, const zval *s2);
+ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(const zval *s1, const zval *s2, const zval *s3);
ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2);
ZEND_API int ZEND_FASTCALL zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2);
@@ -497,10 +497,10 @@ ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1,
ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2);
ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
-ZEND_API bool ZEND_FASTCALL zendi_smart_streq(zend_string *s1, zend_string *s2);
-ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2);
+ZEND_API bool ZEND_FASTCALL zendi_smart_streq(const zend_string *s1, const zend_string *s2);
+ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(const zend_string *s1, const zend_string *s2);
ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2);
-ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2);
+ZEND_API int ZEND_FASTCALL zend_compare_arrays(const zval *a1, const zval *a2);
ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2);
/** Deprecated in favor of ZEND_STRTOL() */
@@ -947,7 +947,7 @@ static zend_always_inline bool fast_equal_check_string(zval *op1, zval *op2)
return zend_compare(op1, op2) == 0;
}
-static zend_always_inline bool fast_is_identical_function(zval *op1, zval *op2)
+static zend_always_inline bool fast_is_identical_function(const zval *op1, const zval *op2)
{
if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
return 0;
@@ -957,7 +957,7 @@ static zend_always_inline bool fast_is_identical_function(zval *op1, zval *op2)
return zend_is_identical(op1, op2);
}
-static zend_always_inline bool fast_is_not_identical_function(zval *op1, zval *op2)
+static zend_always_inline bool fast_is_not_identical_function(const zval *op1, const zval *op2)
{
if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
return 1;