summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2016-12-02 14:00:29 +0300
committerDmitry Stogov <dmitry@zend.com>2016-12-02 14:00:29 +0300
commit5a57b3d6e0c6cc86582f0f1e96fc6385eac51f58 (patch)
tree5726238ffba1b72f4b6e6ec7907859e183db3ab8 /Zend/zend_operators.c
parent2f5090168fe759a0fb94e5d78470a50f0e868796 (diff)
parentdbf39cddd93ad06ce0353695bd02d448a5d6dac9 (diff)
downloadphp-git-5a57b3d6e0c6cc86582f0f1e96fc6385eac51f58.tar.gz
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0: Fixed behavior of failing compound assignments (they shouldn't change the source value).
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c60
1 files changed, 40 insertions, 20 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index beb153c978..bf24c70154 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1201,10 +1201,6 @@ ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {
convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function);
- if (op1 == result) {
- zval_dtor(result);
- }
-
if (op2_lval == 0) {
/* modulus by zero */
if (EG(current_execute_data) && !CG(in_compilation)) {
@@ -1212,10 +1208,16 @@ ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {
} else {
zend_error_noreturn(E_ERROR, "Modulo by zero");
}
- ZVAL_UNDEF(result);
+ if (op1 != result) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
+ if (op1 == result) {
+ zval_dtor(result);
+ }
+
if (op2_lval == -1) {
/* Prevent overflow error/crash if op1==LONG_MIN */
ZVAL_LONG(result, 0);
@@ -1559,13 +1561,12 @@ ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op
convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function);
- if (op1 == result) {
- zval_dtor(result);
- }
-
/* prevent wrapping quirkiness on some processors where << 64 + x == << x */
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
if (EXPECTED(op2_lval > 0)) {
+ if (op1 == result) {
+ zval_dtor(result);
+ }
ZVAL_LONG(result, 0);
return SUCCESS;
} else {
@@ -1574,11 +1575,17 @@ ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op
} else {
zend_error_noreturn(E_ERROR, "Bit shift by negative number");
}
- ZVAL_UNDEF(result);
+ if (op1 != result) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
}
+ if (op1 == result) {
+ zval_dtor(result);
+ }
+
ZVAL_LONG(result, op1_lval << op2_lval);
return SUCCESS;
}
@@ -1590,14 +1597,13 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o
convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function);
- if (op1 == result) {
- zval_dtor(result);
- }
-
/* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
if (EXPECTED(op2_lval > 0)) {
ZVAL_LONG(result, (op1_lval < 0) ? -1 : 0);
+ if (op1 == result) {
+ zval_dtor(result);
+ }
return SUCCESS;
} else {
if (EG(current_execute_data) && !CG(in_compilation)) {
@@ -1605,11 +1611,17 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o
} else {
zend_error_noreturn(E_ERROR, "Bit shift by negative number");
}
- ZVAL_UNDEF(result);
+ if (op1 != result) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
}
+ if (op1 == result) {
+ zval_dtor(result);
+ }
+
ZVAL_LONG(result, op1_lval >> op2_lval);
return SUCCESS;
}
@@ -1617,6 +1629,7 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o
ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
+ zval *orig_op1 = op1;
zval op1_copy, op2_copy;
int use_copy1 = 0, use_copy2 = 0;
@@ -1629,11 +1642,7 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT, concat_function);
use_copy1 = zend_make_printable_zval(op1, &op1_copy);
if (use_copy1) {
- /* We have created a converted copy of op1. Therefore, op1 won't become the result so
- * we have to free it.
- */
if (result == op1) {
- zval_dtor(op1);
if (UNEXPECTED(op1 == op2)) {
op2 = &op1_copy;
}
@@ -1664,7 +1673,15 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /
if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) {
zend_throw_error(NULL, "String size overflow");
- ZVAL_FALSE(result);
+ if (UNEXPECTED(use_copy1)) {
+ zval_dtor(op1);
+ }
+ if (UNEXPECTED(use_copy2)) {
+ zval_dtor(op2);
+ }
+ if (orig_op1 != result) {
+ ZVAL_UNDEF(result);
+ }
return FAILURE;
}
@@ -1674,6 +1691,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /
} else {
result_str = zend_string_alloc(result_len, 0);
memcpy(ZSTR_VAL(result_str), Z_STRVAL_P(op1), op1_len);
+ if (result == orig_op1) {
+ zval_dtor(orig_op1);
+ }
}
/* This has to happen first to account for the cases where result == op1 == op2 and