Skip to content

Commit 148d797

Browse files
committed
Print warning if comparison result will change
1 parent ee7c7a8 commit 148d797

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

Zend/zend_operators.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,89 @@ static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
20192019
}
20202020
/* }}} */
20212021

2022+
static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
2023+
{
2024+
zend_long str_lval;
2025+
double str_dval;
2026+
int num_cmp_result;
2027+
zend_uchar type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 1);
2028+
2029+
if (type == IS_LONG) {
2030+
num_cmp_result = lval > str_lval ? 1 : lval < str_lval ? -1 : 0;
2031+
} else if (type == IS_DOUBLE) {
2032+
double diff = (double) lval - str_dval;
2033+
num_cmp_result = ZEND_NORMALIZE_BOOL(diff);
2034+
} else {
2035+
num_cmp_result = ZEND_NORMALIZE_BOOL(lval);
2036+
}
2037+
2038+
/* TODO Avoid duplicate is_numeric_string call. */
2039+
zend_bool is_numeric = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
2040+
if (is_numeric) {
2041+
/* For numeric strings, the comparison result stays the same. */
2042+
return num_cmp_result;
2043+
}
2044+
2045+
zend_string *lval_as_str = zend_long_to_str(lval);
2046+
int str_cmp_result = zend_binary_strcmp(
2047+
ZSTR_VAL(lval_as_str), ZSTR_LEN(lval_as_str), ZSTR_VAL(str), ZSTR_LEN(str));
2048+
str_cmp_result = ZEND_NORMALIZE_BOOL(str_cmp_result);
2049+
zend_string_release(lval_as_str);
2050+
2051+
if (str_cmp_result != num_cmp_result) {
2052+
zend_error(E_WARNING,
2053+
"Result of comparison between " ZEND_LONG_FMT " and \"%s\" will change (%d to %d)",
2054+
lval, ZSTR_VAL(str), num_cmp_result, str_cmp_result);
2055+
}
2056+
2057+
/* Return old (numeric) comparison result. */
2058+
return num_cmp_result;
2059+
}
2060+
/* }}} */
2061+
2062+
static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
2063+
{
2064+
zend_long str_lval;
2065+
double str_dval;
2066+
int num_cmp_result;
2067+
zend_uchar type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
2068+
2069+
if (type == IS_LONG) {
2070+
double diff = dval - (double) str_lval;
2071+
num_cmp_result = ZEND_NORMALIZE_BOOL(diff);
2072+
} else if (type == IS_DOUBLE) {
2073+
if (dval == str_dval) {
2074+
return 0;
2075+
}
2076+
num_cmp_result = ZEND_NORMALIZE_BOOL(dval - str_dval);
2077+
} else {
2078+
num_cmp_result = ZEND_NORMALIZE_BOOL(dval);
2079+
}
2080+
2081+
/* TODO Avoid duplicate is_numeric_string call. */
2082+
zend_bool is_numeric = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
2083+
if (is_numeric) {
2084+
/* For numeric strings, the comparison result stays the same. */
2085+
return num_cmp_result;
2086+
}
2087+
2088+
zend_string *dval_as_str = zend_strpprintf(0, "%.*G", (int) EG(precision), dval);
2089+
int str_cmp_result = zend_binary_strcmp(
2090+
ZSTR_VAL(dval_as_str), ZSTR_LEN(dval_as_str), ZSTR_VAL(str), ZSTR_LEN(str));
2091+
str_cmp_result = ZEND_NORMALIZE_BOOL(str_cmp_result);
2092+
zend_string_release(dval_as_str);
2093+
2094+
if (str_cmp_result != num_cmp_result) {
2095+
zend_error(E_WARNING,
2096+
"Result of comparison between %G and \"%s\" will change (%d to %d)",
2097+
dval, ZSTR_VAL(str), num_cmp_result, str_cmp_result);
2098+
}
2099+
2100+
/* Return old (numeric) comparison result. */
2101+
return num_cmp_result;
2102+
}
2103+
/* }}} */
2104+
20222105
ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
20232106
{
20242107
int ret;
@@ -2087,6 +2170,32 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
20872170
ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
20882171
return SUCCESS;
20892172

2173+
case TYPE_PAIR(IS_LONG, IS_STRING):
2174+
ZVAL_LONG(result, compare_long_to_string(Z_LVAL_P(op1), Z_STR_P(op2)));
2175+
return SUCCESS;
2176+
2177+
case TYPE_PAIR(IS_STRING, IS_LONG):
2178+
ZVAL_LONG(result, -compare_long_to_string(Z_LVAL_P(op2), Z_STR_P(op1)));
2179+
return SUCCESS;
2180+
2181+
case TYPE_PAIR(IS_DOUBLE, IS_STRING):
2182+
if (zend_isnan(Z_DVAL_P(op1))) {
2183+
ZVAL_LONG(result, 1);
2184+
return SUCCESS;
2185+
}
2186+
2187+
ZVAL_LONG(result, compare_double_to_string(Z_DVAL_P(op1), Z_STR_P(op2)));
2188+
return SUCCESS;
2189+
2190+
case TYPE_PAIR(IS_STRING, IS_DOUBLE):
2191+
if (zend_isnan(Z_DVAL_P(op2))) {
2192+
ZVAL_LONG(result, 1);
2193+
return SUCCESS;
2194+
}
2195+
2196+
ZVAL_LONG(result, -compare_double_to_string(Z_DVAL_P(op2), Z_STR_P(op1)));
2197+
return SUCCESS;
2198+
20902199
case TYPE_PAIR(IS_OBJECT, IS_NULL):
20912200
ZVAL_LONG(result, 1);
20922201
return SUCCESS;

0 commit comments

Comments
 (0)