@@ -1965,7 +1965,7 @@ static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
19651965}
19661966/* }}} */
19671967
1968- static int compare_long_to_string (zend_long lval , zend_string * str ) /* {{{ */
1968+ static int compare_long_to_string (zend_long lval , zend_string * str , zend_bool equality_only ) /* {{{ */
19691969{
19701970 zend_long str_lval ;
19711971 double str_dval ;
@@ -1994,7 +1994,10 @@ static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
19941994 str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
19951995 zend_string_release (lval_as_str );
19961996
1997- if (str_cmp_result != num_cmp_result ) {
1997+ /* Don't report a warning if we're using == and the comparison changed between 1/-1. */
1998+ zend_bool cmp_result_changed_observably = str_cmp_result != num_cmp_result &&
1999+ (!equality_only || str_cmp_result == 0 || num_cmp_result == 0 );
2000+ if (cmp_result_changed_observably ) {
19982001 zend_error (E_WARNING ,
19992002 "Result of comparison between " ZEND_LONG_FMT " and \"%s\" will change (%d to %d)" ,
20002003 lval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
@@ -2005,7 +2008,7 @@ static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
20052008}
20062009/* }}} */
20072010
2008- static int compare_double_to_string (double dval , zend_string * str ) /* {{{ */
2011+ static int compare_double_to_string (double dval , zend_string * str , zend_bool equality_only ) /* {{{ */
20092012{
20102013 zend_long str_lval ;
20112014 double str_dval ;
@@ -2037,7 +2040,10 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
20372040 str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
20382041 zend_string_release (dval_as_str );
20392042
2040- if (str_cmp_result != num_cmp_result ) {
2043+ /* Don't report a warning if we're using == and the comparison changed between 1/-1. */
2044+ zend_bool cmp_result_changed_observably = str_cmp_result != num_cmp_result &&
2045+ (!equality_only || str_cmp_result == 0 || num_cmp_result == 0 );
2046+ if (cmp_result_changed_observably ) {
20412047 zend_error (E_WARNING ,
20422048 "Result of comparison between %G and \"%s\" will change (%d to %d)" ,
20432049 dval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
@@ -2048,7 +2054,7 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
20482054}
20492055/* }}} */
20502056
2051- ZEND_API int ZEND_FASTCALL compare_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
2057+ ZEND_API int ZEND_FASTCALL compare_function_ex (zval * result , zval * op1 , zval * op2 , zend_bool equality_only ) /* {{{ */
20522058{
20532059 int ret ;
20542060 int converted = 0 ;
@@ -2081,7 +2087,7 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
20812087 return SUCCESS ;
20822088
20832089 case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2084- ZVAL_LONG (result , zend_compare_arrays (op1 , op2 ));
2090+ ZVAL_LONG (result , zend_compare_arrays_ex (op1 , op2 , equality_only ));
20852091 return SUCCESS ;
20862092
20872093 case TYPE_PAIR (IS_NULL , IS_NULL ):
@@ -2117,11 +2123,11 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
21172123 return SUCCESS ;
21182124
21192125 case TYPE_PAIR (IS_LONG , IS_STRING ):
2120- ZVAL_LONG (result , compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 )));
2126+ ZVAL_LONG (result , compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 ), equality_only ));
21212127 return SUCCESS ;
21222128
21232129 case TYPE_PAIR (IS_STRING , IS_LONG ):
2124- ZVAL_LONG (result , - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 )));
2130+ ZVAL_LONG (result , - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 ), equality_only ));
21252131 return SUCCESS ;
21262132
21272133 case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
@@ -2130,7 +2136,7 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
21302136 return SUCCESS ;
21312137 }
21322138
2133- ZVAL_LONG (result , compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 )));
2139+ ZVAL_LONG (result , compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ), equality_only ));
21342140 return SUCCESS ;
21352141
21362142 case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
@@ -2139,8 +2145,8 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
21392145 return SUCCESS ;
21402146 }
21412147
2142- ZVAL_LONG (result , - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 )));
2143- return SUCCESS ;
2148+ ZVAL_LONG (result , - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ), equality_only ));
2149+ return SUCCESS ;
21442150
21452151 case TYPE_PAIR (IS_OBJECT , IS_NULL ):
21462152 ZVAL_LONG (result , 1 );
@@ -2188,7 +2194,7 @@ return SUCCESS;
21882194 if (Z_OBJ_HT_P (op1 )-> get ) {
21892195 zval rv ;
21902196 op_free = Z_OBJ_HT_P (op1 )-> get (op1 , & rv );
2191- ret = compare_function (result , op_free , op2 );
2197+ ret = compare_function_ex (result , op_free , op2 , equality_only );
21922198 zend_free_obj_get_result (op_free );
21932199 return ret ;
21942200 } else if (Z_TYPE_P (op2 ) != IS_OBJECT && Z_OBJ_HT_P (op1 )-> cast_object ) {
@@ -2198,7 +2204,7 @@ return SUCCESS;
21982204 zend_free_obj_get_result (& tmp_free );
21992205 return SUCCESS ;
22002206 }
2201- ret = compare_function (result , & tmp_free , op2 );
2207+ ret = compare_function_ex (result , & tmp_free , op2 , equality_only );
22022208 zend_free_obj_get_result (& tmp_free );
22032209 return ret ;
22042210 }
@@ -2207,7 +2213,7 @@ return SUCCESS;
22072213 if (Z_OBJ_HT_P (op2 )-> get ) {
22082214 zval rv ;
22092215 op_free = Z_OBJ_HT_P (op2 )-> get (op2 , & rv );
2210- ret = compare_function (result , op1 , op_free );
2216+ ret = compare_function_ex (result , op1 , op_free , equality_only );
22112217 zend_free_obj_get_result (op_free );
22122218 return ret ;
22132219 } else if (Z_TYPE_P (op1 ) != IS_OBJECT && Z_OBJ_HT_P (op2 )-> cast_object ) {
@@ -2217,7 +2223,7 @@ return SUCCESS;
22172223 zend_free_obj_get_result (& tmp_free );
22182224 return SUCCESS ;
22192225 }
2220- ret = compare_function (result , op1 , & tmp_free );
2226+ ret = compare_function_ex (result , op1 , & tmp_free , equality_only );
22212227 zend_free_obj_get_result (& tmp_free );
22222228 return ret ;
22232229 } else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
@@ -2268,6 +2274,12 @@ return SUCCESS;
22682274}
22692275/* }}} */
22702276
2277+ ZEND_API int ZEND_FASTCALL compare_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
2278+ {
2279+ return compare_function_ex (result , op1 , op2 , 0 );
2280+ }
2281+ /* }}} */
2282+
22712283static int hash_zval_identical_function (zval * z1 , zval * z2 ) /* {{{ */
22722284{
22732285 zval result ;
@@ -2331,7 +2343,7 @@ ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zv
23312343
23322344ZEND_API int ZEND_FASTCALL is_equal_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
23332345{
2334- if (compare_function (result , op1 , op2 ) == FAILURE ) {
2346+ if (compare_function_ex (result , op1 , op2 , 1 ) == FAILURE ) {
23352347 return FAILURE ;
23362348 }
23372349 ZVAL_BOOL (result , (Z_LVAL_P (result ) == 0 ));
@@ -2341,7 +2353,7 @@ ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2)
23412353
23422354ZEND_API int ZEND_FASTCALL is_not_equal_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
23432355{
2344- if (compare_function (result , op1 , op2 ) == FAILURE ) {
2356+ if (compare_function_ex (result , op1 , op2 , 1 ) == FAILURE ) {
23452357 return FAILURE ;
23462358 }
23472359 ZVAL_BOOL (result , (Z_LVAL_P (result ) != 0 ));
@@ -3048,15 +3060,44 @@ static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */
30483060}
30493061/* }}} */
30503062
3063+ static int hash_zval_compare_function_equality (zval * z1 , zval * z2 ) /* {{{ */
3064+ {
3065+ zval result ;
3066+
3067+ if (compare_function_ex (& result , z1 , z2 , 1 )== FAILURE ) {
3068+ return 1 ;
3069+ }
3070+ return Z_LVAL (result );
3071+ }
3072+ /* }}} */
3073+
3074+ ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables_ex (HashTable * ht1 , HashTable * ht2 , zend_bool equality_only ) /* {{{ */
3075+ {
3076+ if (ht1 == ht2 ) {
3077+ return 0 ;
3078+ }
3079+ return zend_hash_compare (ht1 , ht2 ,
3080+ equality_only
3081+ ? (compare_func_t ) hash_zval_compare_function_equality
3082+ : (compare_func_t ) hash_zval_compare_function , 0 );
3083+ }
3084+ /* }}} */
3085+
30513086ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables (HashTable * ht1 , HashTable * ht2 ) /* {{{ */
30523087{
3053- return ht1 == ht2 ? 0 : zend_hash_compare (ht1 , ht2 , (compare_func_t ) hash_zval_compare_function , 0 );
3088+ return zend_compare_symbol_tables_ex (ht1 , ht2 , 0 );
3089+ }
3090+ /* }}} */
3091+
3092+ ZEND_API int ZEND_FASTCALL zend_compare_arrays_ex (zval * a1 , zval * a2 , zend_bool equality_only ) /* {{{ */
3093+ {
3094+ return zend_compare_symbol_tables_ex (Z_ARRVAL_P (a1 ), Z_ARRVAL_P (a2 ), equality_only );
30543095}
30553096/* }}} */
30563097
30573098ZEND_API int ZEND_FASTCALL zend_compare_arrays (zval * a1 , zval * a2 ) /* {{{ */
30583099{
3059- return zend_compare_symbol_tables (Z_ARRVAL_P (a1 ), Z_ARRVAL_P (a2 ));
3100+ return zend_compare_symbol_tables_ex (Z_ARRVAL_P (a1 ), Z_ARRVAL_P (a2 ), 0 );
30603101}
30613102/* }}} */
30623103
0 commit comments