Skip to content

Commit 38493a0

Browse files
committed
Don't throw a warning for 1/-1 flips on equality comparisons
While the comparison result changes, the equality comparison is not going to care about it in the end.
1 parent 3b74eb1 commit 38493a0

File tree

4 files changed

+80
-36
lines changed

4 files changed

+80
-36
lines changed

Zend/zend_operators.c

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
22712283
static 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

23322344
ZEND_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

23422354
ZEND_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+
30513086
ZEND_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

30573098
ZEND_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

Zend/zend_operators.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ static zend_always_inline int i_zend_is_true(zval *op)
352352
return result;
353353
}
354354

355+
ZEND_API int ZEND_FASTCALL compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool equality_only);
355356
ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2);
356357

357358
ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2);
@@ -383,7 +384,9 @@ ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1
383384

384385
ZEND_API int ZEND_FASTCALL zendi_smart_streq(zend_string *s1, zend_string *s2);
385386
ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2);
387+
ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables_ex(HashTable *ht1, HashTable *ht2, zend_bool equality_only);
386388
ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2);
389+
ZEND_API int ZEND_FASTCALL zend_compare_arrays_ex(zval *a1, zval *a2, zend_bool equality_only);
387390
ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2);
388391
ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2);
389392

@@ -754,7 +757,7 @@ static zend_always_inline int fast_equal_check_function(zval *op1, zval *op2)
754757
return zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
755758
}
756759
}
757-
compare_function(&result, op1, op2);
760+
compare_function_ex(&result, op1, op2, 1);
758761
return Z_LVAL(result) == 0;
759762
}
760763

@@ -764,7 +767,7 @@ static zend_always_inline int fast_equal_check_long(zval *op1, zval *op2)
764767
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
765768
return Z_LVAL_P(op1) == Z_LVAL_P(op2);
766769
}
767-
compare_function(&result, op1, op2);
770+
compare_function_ex(&result, op1, op2, 1);
768771
return Z_LVAL(result) == 0;
769772
}
770773

@@ -774,7 +777,7 @@ static zend_always_inline int fast_equal_check_string(zval *op1, zval *op2)
774777
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
775778
return zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
776779
}
777-
compare_function(&result, op1, op2);
780+
compare_function_ex(&result, op1, op2, 1);
778781
return Z_LVAL(result) == 0;
779782
}
780783

Zend/zend_vm_def.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR
436436
op2 = ZVAL_UNDEFINED_OP2();
437437
}
438438
result = EX_VAR(opline->result.var);
439-
compare_function(result, op1, op2);
439+
compare_function_ex(result, op1, op2, 1);
440440
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
441441
FREE_OP1();
442442
FREE_OP2();
@@ -494,7 +494,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TM
494494
op2 = ZVAL_UNDEFINED_OP2();
495495
}
496496
result = EX_VAR(opline->result.var);
497-
compare_function(result, op1, op2);
497+
compare_function_ex(result, op1, op2, 1);
498498
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
499499
FREE_OP1();
500500
FREE_OP2();

Zend/zend_vm_execute.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4459,7 +4459,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CON
44594459
op2 = ZVAL_UNDEFINED_OP2();
44604460
}
44614461
result = EX_VAR(opline->result.var);
4462-
compare_function(result, op1, op2);
4462+
compare_function_ex(result, op1, op2, 1);
44634463
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
44644464

44654465

@@ -4517,7 +4517,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC
45174517
op2 = ZVAL_UNDEFINED_OP2();
45184518
}
45194519
result = EX_VAR(opline->result.var);
4520-
compare_function(result, op1, op2);
4520+
compare_function_ex(result, op1, op2, 1);
45214521
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
45224522

45234523

@@ -13384,7 +13384,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN
1338413384
op2 = ZVAL_UNDEFINED_OP2();
1338513385
}
1338613386
result = EX_VAR(opline->result.var);
13387-
compare_function(result, op1, op2);
13387+
compare_function_ex(result, op1, op2, 1);
1338813388
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
1338913389
zval_ptr_dtor_nogc(free_op1);
1339013390

@@ -13442,7 +13442,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST
1344213442
op2 = ZVAL_UNDEFINED_OP2();
1344313443
}
1344413444
result = EX_VAR(opline->result.var);
13445-
compare_function(result, op1, op2);
13445+
compare_function_ex(result, op1, op2, 1);
1344613446
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
1344713447
zval_ptr_dtor_nogc(free_op1);
1344813448

@@ -14991,7 +14991,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA
1499114991
op2 = ZVAL_UNDEFINED_OP2();
1499214992
}
1499314993
result = EX_VAR(opline->result.var);
14994-
compare_function(result, op1, op2);
14994+
compare_function_ex(result, op1, op2, 1);
1499514995
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
1499614996
zval_ptr_dtor_nogc(free_op1);
1499714997
zval_ptr_dtor_nogc(free_op2);
@@ -15049,7 +15049,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA
1504915049
op2 = ZVAL_UNDEFINED_OP2();
1505015050
}
1505115051
result = EX_VAR(opline->result.var);
15052-
compare_function(result, op1, op2);
15052+
compare_function_ex(result, op1, op2, 1);
1505315053
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
1505415054
zval_ptr_dtor_nogc(free_op1);
1505515055
zval_ptr_dtor_nogc(free_op2);
@@ -40602,7 +40602,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER
4060240602
op2 = ZVAL_UNDEFINED_OP2();
4060340603
}
4060440604
result = EX_VAR(opline->result.var);
40605-
compare_function(result, op1, op2);
40605+
compare_function_ex(result, op1, op2, 1);
4060640606
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
4060740607

4060840608

@@ -40660,7 +40660,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN
4066040660
op2 = ZVAL_UNDEFINED_OP2();
4066140661
}
4066240662
result = EX_VAR(opline->result.var);
40663-
compare_function(result, op1, op2);
40663+
compare_function_ex(result, op1, op2, 1);
4066440664
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
4066540665

4066640666

@@ -44749,7 +44749,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLE
4474944749
op2 = ZVAL_UNDEFINED_OP2();
4475044750
}
4475144751
result = EX_VAR(opline->result.var);
44752-
compare_function(result, op1, op2);
44752+
compare_function_ex(result, op1, op2, 1);
4475344753
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
4475444754

4475544755
zval_ptr_dtor_nogc(free_op2);
@@ -44807,7 +44807,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HA
4480744807
op2 = ZVAL_UNDEFINED_OP2();
4480844808
}
4480944809
result = EX_VAR(opline->result.var);
44810-
compare_function(result, op1, op2);
44810+
compare_function_ex(result, op1, op2, 1);
4481144811
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
4481244812

4481344813
zval_ptr_dtor_nogc(free_op2);
@@ -50743,7 +50743,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE
5074350743
op2 = ZVAL_UNDEFINED_OP2();
5074450744
}
5074550745
result = EX_VAR(opline->result.var);
50746-
compare_function(result, op1, op2);
50746+
compare_function_ex(result, op1, op2, 1);
5074750747
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
5074850748

5074950749

@@ -50801,7 +50801,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE
5080150801
op2 = ZVAL_UNDEFINED_OP2();
5080250802
}
5080350803
result = EX_VAR(opline->result.var);
50804-
compare_function(result, op1, op2);
50804+
compare_function_ex(result, op1, op2, 1);
5080550805
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
5080650806

5080750807

0 commit comments

Comments
 (0)