summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c104
1 files changed, 75 insertions, 29 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 50557e56d8..1710ba44dd 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -147,7 +147,7 @@ static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */
}
/* }}} */
-ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
+void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent) /* {{{ */
{
try_again:
switch (Z_TYPE_P(op)) {
@@ -159,8 +159,11 @@ try_again:
zend_string *str;
str = Z_STR_P(op);
- if ((Z_TYPE_INFO_P(op)=is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
+ if ((Z_TYPE_INFO_P(op)=is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &Z_LVAL_P(op), &Z_DVAL_P(op), silent ? 1 : -1)) == 0) {
ZVAL_LONG(op, 0);
+ if (!silent) {
+ zend_error(E_WARNING, "A non-numeric value encountered");
+ }
}
zend_string_release(str);
break;
@@ -186,18 +189,27 @@ try_again:
}
/* }}} */
+ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
+{
+ _convert_scalar_to_number(op, 1);
+}
+/* }}} */
+
/* {{{ zendi_convert_scalar_to_number */
-#define zendi_convert_scalar_to_number(op, holder, result) \
+#define zendi_convert_scalar_to_number(op, holder, result, silent) \
if (op==result) { \
if (Z_TYPE_P(op) != IS_LONG) { \
- convert_scalar_to_number(op); \
+ _convert_scalar_to_number(op, silent); \
} \
} else { \
switch (Z_TYPE_P(op)) { \
case IS_STRING: \
{ \
- if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
+ if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), silent ? 1 : -1)) == 0) { \
ZVAL_LONG(&(holder), 0); \
+ if (!silent) { \
+ zend_error(E_WARNING, "A non-numeric value encountered"); \
+ } \
} \
(op) = &(holder); \
break; \
@@ -258,7 +270,7 @@ try_again:
} \
} \
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func); \
- op1_lval = _zval_get_long_func(op1); \
+ op1_lval = _zval_get_long_func_noisy(op1); \
} else { \
op1_lval = Z_LVAL_P(op1); \
} \
@@ -273,7 +285,7 @@ try_again:
} \
} \
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op); \
- op2_lval = _zval_get_long_func(op2); \
+ op2_lval = _zval_get_long_func_noisy(op2); \
} else { \
op2_lval = Z_LVAL_P(op2); \
} \
@@ -313,8 +325,11 @@ try_again:
case IS_STRING:
{
zend_string *str = Z_STR_P(op);
-
- ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base));
+ if (base == 10) {
+ ZVAL_LONG(op, zval_get_long(op));
+ } else {
+ ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base));
+ }
zend_string_release(str);
}
break;
@@ -728,7 +743,7 @@ ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
}
/* }}} */
-ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */
+static zend_always_inline zend_long ZEND_FASTCALL _zval_get_long_func_ex(zval *op, zend_bool silent) /* {{{ */
{
try_again:
switch (Z_TYPE_P(op)) {
@@ -744,7 +759,26 @@ try_again:
case IS_DOUBLE:
return zend_dval_to_lval(Z_DVAL_P(op));
case IS_STRING:
- return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10);
+ {
+ zend_uchar type;
+ zend_long lval;
+ double dval;
+ if (0 == (type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval, silent ? 1 : -1))) {
+ if (!silent) {
+ zend_error(E_WARNING, "A non-numeric value encountered");
+ }
+ return 0;
+ } else if (EXPECTED(type == IS_LONG)) {
+ return lval;
+ } else {
+ /* Previously we used strtol here, not is_numeric_string,
+ * and strtol gives you LONG_MAX/_MIN on overflow.
+ * We use use saturating conversion to emulate strtol()'s
+ * behaviour.
+ */
+ return zend_dval_to_lval_cap(dval);
+ }
+ }
case IS_ARRAY:
return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0;
case IS_OBJECT:
@@ -766,6 +800,18 @@ try_again:
}
/* }}} */
+ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */
+{
+ return _zval_get_long_func_ex(op, 1);
+}
+/* }}} */
+
+static zend_long ZEND_FASTCALL _zval_get_long_func_noisy(zval *op) /* {{{ */
+{
+ return _zval_get_long_func_ex(op, 0);
+}
+/* }}} */
+
ZEND_API double ZEND_FASTCALL _zval_get_double_func(zval *op) /* {{{ */
{
try_again:
@@ -916,8 +962,8 @@ ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {
} else if (!converted) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
- zendi_convert_scalar_to_number(op1, op1_copy, result);
- zendi_convert_scalar_to_number(op2, op2_copy, result);
+ zendi_convert_scalar_to_number(op1, op1_copy, result, 0);
+ zendi_convert_scalar_to_number(op2, op2_copy, result, 0);
converted = 1;
} else {
zend_throw_error(NULL, "Unsupported operand types");
@@ -969,8 +1015,8 @@ ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {
} else if (!converted) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
- zendi_convert_scalar_to_number(op1, op1_copy, result);
- zendi_convert_scalar_to_number(op2, op2_copy, result);
+ zendi_convert_scalar_to_number(op1, op1_copy, result, 0);
+ zendi_convert_scalar_to_number(op2, op2_copy, result, 0);
converted = 1;
} else {
zend_throw_error(NULL, "Unsupported operand types");
@@ -1016,8 +1062,8 @@ ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* {
} else if (!converted) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function);
- zendi_convert_scalar_to_number(op1, op1_copy, result);
- zendi_convert_scalar_to_number(op2, op2_copy, result);
+ zendi_convert_scalar_to_number(op1, op1_copy, result, 0);
+ zendi_convert_scalar_to_number(op2, op2_copy, result, 0);
converted = 1;
} else {
zend_throw_error(NULL, "Unsupported operand types");
@@ -1098,13 +1144,13 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* {
ZVAL_LONG(result, 0);
return SUCCESS;
} else {
- zendi_convert_scalar_to_number(op1, op1_copy, result);
+ zendi_convert_scalar_to_number(op1, op1_copy, result, 0);
}
if (Z_TYPE_P(op2) == IS_ARRAY) {
ZVAL_LONG(result, 1L);
return SUCCESS;
} else {
- zendi_convert_scalar_to_number(op2, op2_copy, result);
+ zendi_convert_scalar_to_number(op2, op2_copy, result, 0);
}
converted = 1;
} else {
@@ -1169,8 +1215,8 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
} else if (!converted) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function);
- zendi_convert_scalar_to_number(op1, op1_copy, result);
- zendi_convert_scalar_to_number(op2, op2_copy, result);
+ zendi_convert_scalar_to_number(op1, op1_copy, result, 0);
+ zendi_convert_scalar_to_number(op2, op2_copy, result, 0);
converted = 1;
} else {
zend_throw_error(NULL, "Unsupported operand types");
@@ -1377,13 +1423,13 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function);
- op1_lval = _zval_get_long_func(op1);
+ op1_lval = _zval_get_long_func_noisy(op1);
} else {
op1_lval = Z_LVAL_P(op1);
}
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR);
- op2_lval = _zval_get_long_func(op2);
+ op2_lval = _zval_get_long_func_noisy(op2);
} else {
op2_lval = Z_LVAL_P(op2);
}
@@ -1444,13 +1490,13 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function);
- op1_lval = _zval_get_long_func(op1);
+ op1_lval = _zval_get_long_func_noisy(op1);
} else {
op1_lval = Z_LVAL_P(op1);
}
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND);
- op2_lval = _zval_get_long_func(op2);
+ op2_lval = _zval_get_long_func_noisy(op2);
} else {
op2_lval = Z_LVAL_P(op2);
}
@@ -1511,13 +1557,13 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function);
- op1_lval = _zval_get_long_func(op1);
+ op1_lval = _zval_get_long_func_noisy(op1);
} else {
op1_lval = Z_LVAL_P(op1);
}
if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR);
- op2_lval = _zval_get_long_func(op2);
+ op2_lval = _zval_get_long_func_noisy(op2);
} else {
op2_lval = Z_LVAL_P(op2);
}
@@ -1944,8 +1990,8 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1);
return SUCCESS;
} else {
- zendi_convert_scalar_to_number(op1, op1_copy, result);
- zendi_convert_scalar_to_number(op2, op2_copy, result);
+ zendi_convert_scalar_to_number(op1, op1_copy, result, 1);
+ zendi_convert_scalar_to_number(op2, op2_copy, result, 1);
converted = 1;
}
} else if (Z_TYPE_P(op1)==IS_ARRAY) {