@@ -2019,7 +2019,7 @@ static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
2019
2019
}
2020
2020
/* }}} */
2021
2021
2022
- static int compare_long_to_string (zend_long lval , zend_string * str ) /* {{{ */
2022
+ static int compare_long_to_string (zend_long lval , zend_string * str , zend_bool equality_only ) /* {{{ */
2023
2023
{
2024
2024
zend_long str_lval ;
2025
2025
double str_dval ;
@@ -2048,7 +2048,10 @@ static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
2048
2048
str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
2049
2049
zend_string_release (lval_as_str );
2050
2050
2051
- if (str_cmp_result != num_cmp_result ) {
2051
+ /* Don't report a warning if we're using == and the comparison changed between 1/-1. */
2052
+ zend_bool cmp_result_changed_observably = str_cmp_result != num_cmp_result &&
2053
+ (!equality_only || str_cmp_result == 0 || num_cmp_result == 0 );
2054
+ if (cmp_result_changed_observably ) {
2052
2055
zend_error (E_WARNING ,
2053
2056
"Result of comparison between " ZEND_LONG_FMT " and \"%s\" will change (%d to %d)" ,
2054
2057
lval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
@@ -2059,7 +2062,7 @@ static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
2059
2062
}
2060
2063
/* }}} */
2061
2064
2062
- static int compare_double_to_string (double dval , zend_string * str ) /* {{{ */
2065
+ static int compare_double_to_string (double dval , zend_string * str , zend_bool equality_only ) /* {{{ */
2063
2066
{
2064
2067
zend_long str_lval ;
2065
2068
double str_dval ;
@@ -2091,7 +2094,10 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
2091
2094
str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
2092
2095
zend_string_release (dval_as_str );
2093
2096
2094
- if (str_cmp_result != num_cmp_result ) {
2097
+ /* Don't report a warning if we're using == and the comparison changed between 1/-1. */
2098
+ zend_bool cmp_result_changed_observably = str_cmp_result != num_cmp_result &&
2099
+ (!equality_only || str_cmp_result == 0 || num_cmp_result == 0 );
2100
+ if (cmp_result_changed_observably ) {
2095
2101
zend_error (E_WARNING ,
2096
2102
"Result of comparison between %G and \"%s\" will change (%d to %d)" ,
2097
2103
dval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
@@ -2102,7 +2108,7 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
2102
2108
}
2103
2109
/* }}} */
2104
2110
2105
- ZEND_API int ZEND_FASTCALL compare_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
2111
+ ZEND_API int ZEND_FASTCALL compare_function_ex (zval * result , zval * op1 , zval * op2 , zend_bool equality_only ) /* {{{ */
2106
2112
{
2107
2113
int ret ;
2108
2114
int converted = 0 ;
@@ -2135,7 +2141,7 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
2135
2141
return SUCCESS ;
2136
2142
2137
2143
case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2138
- ZVAL_LONG (result , zend_compare_arrays (op1 , op2 ));
2144
+ ZVAL_LONG (result , zend_compare_arrays_ex (op1 , op2 , equality_only ));
2139
2145
return SUCCESS ;
2140
2146
2141
2147
case TYPE_PAIR (IS_NULL , IS_NULL ):
@@ -2171,11 +2177,11 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
2171
2177
return SUCCESS ;
2172
2178
2173
2179
case TYPE_PAIR (IS_LONG , IS_STRING ):
2174
- ZVAL_LONG (result , compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 )));
2180
+ ZVAL_LONG (result , compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 ), equality_only ));
2175
2181
return SUCCESS ;
2176
2182
2177
2183
case TYPE_PAIR (IS_STRING , IS_LONG ):
2178
- ZVAL_LONG (result , - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 )));
2184
+ ZVAL_LONG (result , - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 ), equality_only ));
2179
2185
return SUCCESS ;
2180
2186
2181
2187
case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
@@ -2184,7 +2190,7 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
2184
2190
return SUCCESS ;
2185
2191
}
2186
2192
2187
- ZVAL_LONG (result , compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 )));
2193
+ ZVAL_LONG (result , compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ), equality_only ));
2188
2194
return SUCCESS ;
2189
2195
2190
2196
case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
@@ -2193,8 +2199,8 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
2193
2199
return SUCCESS ;
2194
2200
}
2195
2201
2196
- ZVAL_LONG (result , - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 )));
2197
- return SUCCESS ;
2202
+ ZVAL_LONG (result , - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ), equality_only ));
2203
+ return SUCCESS ;
2198
2204
2199
2205
case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2200
2206
ZVAL_LONG (result , 1 );
@@ -2242,7 +2248,7 @@ return SUCCESS;
2242
2248
if (Z_OBJ_HT_P (op1 )-> get ) {
2243
2249
zval rv ;
2244
2250
op_free = Z_OBJ_HT_P (op1 )-> get (op1 , & rv );
2245
- ret = compare_function (result , op_free , op2 );
2251
+ ret = compare_function_ex (result , op_free , op2 , equality_only );
2246
2252
zend_free_obj_get_result (op_free );
2247
2253
return ret ;
2248
2254
} else if (Z_TYPE_P (op2 ) != IS_OBJECT && Z_OBJ_HT_P (op1 )-> cast_object ) {
@@ -2252,7 +2258,7 @@ return SUCCESS;
2252
2258
zend_free_obj_get_result (& tmp_free );
2253
2259
return SUCCESS ;
2254
2260
}
2255
- ret = compare_function (result , & tmp_free , op2 );
2261
+ ret = compare_function_ex (result , & tmp_free , op2 , equality_only );
2256
2262
zend_free_obj_get_result (& tmp_free );
2257
2263
return ret ;
2258
2264
}
@@ -2261,7 +2267,7 @@ return SUCCESS;
2261
2267
if (Z_OBJ_HT_P (op2 )-> get ) {
2262
2268
zval rv ;
2263
2269
op_free = Z_OBJ_HT_P (op2 )-> get (op2 , & rv );
2264
- ret = compare_function (result , op1 , op_free );
2270
+ ret = compare_function_ex (result , op1 , op_free , equality_only );
2265
2271
zend_free_obj_get_result (op_free );
2266
2272
return ret ;
2267
2273
} else if (Z_TYPE_P (op1 ) != IS_OBJECT && Z_OBJ_HT_P (op2 )-> cast_object ) {
@@ -2271,7 +2277,7 @@ return SUCCESS;
2271
2277
zend_free_obj_get_result (& tmp_free );
2272
2278
return SUCCESS ;
2273
2279
}
2274
- ret = compare_function (result , op1 , & tmp_free );
2280
+ ret = compare_function_ex (result , op1 , & tmp_free , equality_only );
2275
2281
zend_free_obj_get_result (& tmp_free );
2276
2282
return ret ;
2277
2283
} else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
@@ -2322,6 +2328,12 @@ return SUCCESS;
2322
2328
}
2323
2329
/* }}} */
2324
2330
2331
+ ZEND_API int ZEND_FASTCALL compare_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
2332
+ {
2333
+ return compare_function_ex (result , op1 , op2 , 0 );
2334
+ }
2335
+ /* }}} */
2336
+
2325
2337
static int hash_zval_identical_function (zval * z1 , zval * z2 ) /* {{{ */
2326
2338
{
2327
2339
/* is_identical_function() returns 1 in case of identity and 0 in case
@@ -2380,7 +2392,7 @@ ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zv
2380
2392
2381
2393
ZEND_API int ZEND_FASTCALL is_equal_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
2382
2394
{
2383
- if (compare_function (result , op1 , op2 ) == FAILURE ) {
2395
+ if (compare_function_ex (result , op1 , op2 , 1 ) == FAILURE ) {
2384
2396
return FAILURE ;
2385
2397
}
2386
2398
ZVAL_BOOL (result , (Z_LVAL_P (result ) == 0 ));
@@ -2390,7 +2402,7 @@ ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2)
2390
2402
2391
2403
ZEND_API int ZEND_FASTCALL is_not_equal_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
2392
2404
{
2393
- if (compare_function (result , op1 , op2 ) == FAILURE ) {
2405
+ if (compare_function_ex (result , op1 , op2 , 1 ) == FAILURE ) {
2394
2406
return FAILURE ;
2395
2407
}
2396
2408
ZVAL_BOOL (result , (Z_LVAL_P (result ) != 0 ));
@@ -3076,15 +3088,44 @@ static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */
3076
3088
}
3077
3089
/* }}} */
3078
3090
3091
+ static int hash_zval_compare_function_equality (zval * z1 , zval * z2 ) /* {{{ */
3092
+ {
3093
+ zval result ;
3094
+
3095
+ if (compare_function_ex (& result , z1 , z2 , 1 )== FAILURE ) {
3096
+ return 1 ;
3097
+ }
3098
+ return Z_LVAL (result );
3099
+ }
3100
+ /* }}} */
3101
+
3102
+ ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables_ex (HashTable * ht1 , HashTable * ht2 , zend_bool equality_only ) /* {{{ */
3103
+ {
3104
+ if (ht1 == ht2 ) {
3105
+ return 0 ;
3106
+ }
3107
+ return zend_hash_compare (ht1 , ht2 ,
3108
+ equality_only
3109
+ ? (compare_func_t ) hash_zval_compare_function_equality
3110
+ : (compare_func_t ) hash_zval_compare_function , 0 );
3111
+ }
3112
+ /* }}} */
3113
+
3079
3114
ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables (HashTable * ht1 , HashTable * ht2 ) /* {{{ */
3080
3115
{
3081
- return ht1 == ht2 ? 0 : zend_hash_compare (ht1 , ht2 , (compare_func_t ) hash_zval_compare_function , 0 );
3116
+ return zend_compare_symbol_tables_ex (ht1 , ht2 , 0 );
3117
+ }
3118
+ /* }}} */
3119
+
3120
+ ZEND_API int ZEND_FASTCALL zend_compare_arrays_ex (zval * a1 , zval * a2 , zend_bool equality_only ) /* {{{ */
3121
+ {
3122
+ return zend_compare_symbol_tables_ex (Z_ARRVAL_P (a1 ), Z_ARRVAL_P (a2 ), equality_only );
3082
3123
}
3083
3124
/* }}} */
3084
3125
3085
3126
ZEND_API int ZEND_FASTCALL zend_compare_arrays (zval * a1 , zval * a2 ) /* {{{ */
3086
3127
{
3087
- return zend_compare_symbol_tables (Z_ARRVAL_P (a1 ), Z_ARRVAL_P (a2 ));
3128
+ return zend_compare_symbol_tables_ex (Z_ARRVAL_P (a1 ), Z_ARRVAL_P (a2 ), 0 );
3088
3129
}
3089
3130
/* }}} */
3090
3131
0 commit comments