summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-04-06 14:30:05 +0300
committerDmitry Stogov <dmitry@zend.com>2015-04-06 14:30:05 +0300
commitcae0147ed3ceb55fcb1bc059b8e8ea6a36ea69a8 (patch)
tree4ca16379ac8d5cab749f07747e2599ee23a4d175 /Zend/zend_operators.c
parentcaf9219dea58dcc6ef6da2b3b86a1e9808363bff (diff)
downloadphp-git-cae0147ed3ceb55fcb1bc059b8e8ea6a36ea69a8.tar.gz
Fixed weird operators behavior. Division by zero now emits warning and returns +/-INF, modulo by zero and intdid() throws an exception, shifts by negative offset throw exceptions. Compile-time evaluation of division by zero is disabled.
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 8ded1f2de9..c454ec4f8e 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1064,6 +1064,22 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* {
}
/* }}} */
+static zend_always_inline void make_inf(zval *result, int neg) /* {{{ */
+{
+#if HAVE_HUGE_VAL_INF
+ ZVAL_DOUBLE(result, neg ? -HUGE_VAL : HUGE_VAL);
+#elif defined(__i386__) || defined(_X86_) || defined(ALPHA) || defined(_ALPHA) || defined(__alpha)
+ result->value.ww.w1 = neg ? 0xfff00000 : 0x7ff00000;
+ result->value.ww.w2 = 0
+ Z_TYPE_INFO_P(result) = IS_DOUBLE;
+#elif HAVE_ATOF_ACCEPTS_INF
+ ZVAL_DOUBLE(neg ? aatof("-INF") : tof("INF"));
+#else
+ ZVAL_DOUBLE(result, neg ? (-1.0/0.0) : (1.0/0.0));
+#endif
+}
+/* }}} */
+
ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
zval op1_copy, op2_copy;
@@ -1074,8 +1090,8 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
case TYPE_PAIR(IS_LONG, IS_LONG):
if (Z_LVAL_P(op2) == 0) {
zend_error(E_WARNING, "Division by zero");
- ZVAL_FALSE(result);
- return FAILURE; /* division by zero */
+ make_inf(result, Z_LVAL_P(op1) < 0);
+ return SUCCESS;
} else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
/* Prevent overflow error/crash */
ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
@@ -1091,8 +1107,8 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
case TYPE_PAIR(IS_DOUBLE, IS_LONG):
if (Z_LVAL_P(op2) == 0) {
zend_error(E_WARNING, "Division by zero");
- ZVAL_FALSE(result);
- return FAILURE; /* division by zero */
+ make_inf(result, Z_DVAL_P(op1) < 0.0);
+ return SUCCESS;
}
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
return SUCCESS;
@@ -1100,8 +1116,8 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
case TYPE_PAIR(IS_LONG, IS_DOUBLE):
if (Z_DVAL_P(op2) == 0) {
zend_error(E_WARNING, "Division by zero");
- ZVAL_FALSE(result);
- return FAILURE; /* division by zero */
+ make_inf(result, Z_LVAL_P(op1) < 0);
+ return SUCCESS;
}
ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
return SUCCESS;
@@ -1109,8 +1125,8 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {
case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
if (Z_DVAL_P(op2) == 0) {
zend_error(E_WARNING, "Division by zero");
- ZVAL_FALSE(result);
- return FAILURE; /* division by zero */
+ make_inf(result, Z_LVAL_P(op1) < 0.0);
+ return SUCCESS;
}
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
return SUCCESS;
@@ -1146,9 +1162,13 @@ ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {
}
if (op2_lval == 0) {
- zend_error(E_WARNING, "Division by zero");
- ZVAL_FALSE(result);
- return FAILURE; /* modulus by zero */
+ /* modulus by zero */
+ if (EG(current_execute_data) && !CG(in_compilation)) {
+ zend_throw_exception_ex(NULL, 0, "Division by zero");
+ } else {
+ zend_error_noreturn(E_ERROR, "Division by zero");
+ }
+ return FAILURE;
}
if (op2_lval == -1) {
@@ -1459,8 +1479,11 @@ ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op
ZVAL_LONG(result, 0);
return SUCCESS;
} else {
- zend_error(E_WARNING, "Bit shift by negative number");
- ZVAL_FALSE(result);
+ if (EG(current_execute_data) && !CG(in_compilation)) {
+ zend_throw_exception_ex(NULL, 0, "Bit shift by negative number");
+ } else {
+ zend_error_noreturn(E_ERROR, "Bit shift by negative number");
+ }
return FAILURE;
}
}
@@ -1486,8 +1509,11 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o
ZVAL_LONG(result, (op1_lval < 0) ? -1 : 0);
return SUCCESS;
} else {
- zend_error(E_WARNING, "Bit shift by negative number");
- ZVAL_FALSE(result);
+ if (EG(current_execute_data) && !CG(in_compilation)) {
+ zend_throw_exception_ex(NULL, 0, "Bit shift by negative number");
+ } else {
+ zend_error_noreturn(E_ERROR, "Bit shift by negative number");
+ }
return FAILURE;
}
}