summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.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_compile.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_compile.c')
-rw-r--r--Zend/zend_compile.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 70359123c4..ac10a2ad74 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5538,12 +5538,30 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
zend_compile_expr(&right_node, right_ast);
if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
- result->op_type = IS_CONST;
- zend_ct_eval_binary_op(&result->u.constant, opcode,
- &left_node.u.constant, &right_node.u.constant);
- zval_ptr_dtor(&left_node.u.constant);
- zval_ptr_dtor(&right_node.u.constant);
- return;
+ do {
+ /* don't evaluate divsion by zero at compile-time */
+ if (opcode == ZEND_DIV) {
+ zval *op2 = &right_node.u.constant;
+
+ convert_scalar_to_number(op2);
+ if (Z_TYPE_P(op2) == IS_LONG) {
+ if (Z_LVAL_P(op2) == 0) {
+ break;
+ }
+ } else if (Z_TYPE_P(op2) == IS_DOUBLE) {
+ if (Z_DVAL_P(op2) == 0.0) {
+ break;
+ }
+ }
+ }
+
+ result->op_type = IS_CONST;
+ zend_ct_eval_binary_op(&result->u.constant, opcode,
+ &left_node.u.constant, &right_node.u.constant);
+ zval_ptr_dtor(&left_node.u.constant);
+ zval_ptr_dtor(&right_node.u.constant);
+ return;
+ } while (0);
}
do {
@@ -6937,6 +6955,22 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
return;
}
+ /* don't evaluate divsion by zero at compile-time */
+ if (ast->attr == ZEND_DIV) {
+ zval *op2 = zend_ast_get_zval(ast->child[1]);
+
+ convert_scalar_to_number(op2);
+ if (Z_TYPE_P(op2) == IS_LONG) {
+ if (Z_LVAL_P(op2) == 0) {
+ return;
+ }
+ } else if (Z_TYPE_P(op2) == IS_DOUBLE) {
+ if (Z_DVAL_P(op2) == 0.0) {
+ return;
+ }
+ }
+ }
+
zend_ct_eval_binary_op(&result, ast->attr,
zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]));
break;