com php-src: Fixed bug #68896 (Changing ArrayObject value cause Segment Fault): Zend/tests/bug68896.phpt Zend/zend_execute.c
| From: | Dmitry Stogov | Date: | Mon, 26 Jan 2015 08:25:05 +0000 |
| Subject: | com php-src: Fixed bug #68896 (Changing ArrayObject value cause Segment Fault): Zend/tests/bug68896.phpt Zend/zend_execute.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-84365@lists.php.net to get a copy of this message | ||
Commit: 371dc9b6a659399ede7d3c784f3c6ff800045ab2
Author: Dmitry Stogov <dmitry@zend.com> Mon, 26 Jan 2015 11:25:05 +0300
Parents: 91045c4d74c594ec56d135ec9ecec4f007918a06
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=371dc9b6a659399ede7d3c784f3c6ff800045ab2
Log:
Fixed bug #68896 (Changing ArrayObject value cause Segment Fault)
Bugs:
https://bugs.php.net/68896
Changed paths:
A Zend/tests/bug68896.phpt
M Zend/zend_execute.c
Diff:
diff --git a/Zend/tests/bug68896.phpt b/Zend/tests/bug68896.phpt
new file mode 100644
index 0000000..31823a2
--- /dev/null
+++ b/Zend/tests/bug68896.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Bug #68896 (Changing ArrayObject value cause Segment Fault)
+--FILE--
+<?php
+class A implements ArrayAccess {
+ private $a = [];
+ function offsetGet($offset) {
+ return $this->a[$offset];
+ }
+ function offsetSet($offset, $value) {
+ $this->a[$offset] = $value;
+ }
+ function offsetExists($offset) {
+ isset($this->a[$offset]);
+ }
+ function offsetUnset($offset) {
+ unset($this->a[$offset]);
+ }
+}
+
+$obj = new ArrayObject(["a" => 1]);
+$obj["a"] .= "test";
+var_dump($obj["a"]);
+
+$obj = new A;
+$obj["a"] = 1;
+$obj["a"] .= "test";
+var_dump($obj["a"]);
+--EXPECT--
+string(5) "1test"
+string(5) "1test"
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index c71c032..3092d05 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -925,7 +925,7 @@ static zend_always_inline void zend_assign_to_object_dim(zval *retval, zval *obj
static void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *value, zval *retval,
int (*binary_op)(zval *result, zval *op1, zval *op2))
{
zval *z;
- zval rv;
+ zval rv, res;
if (Z_OBJ_HT_P(object)->read_dimension &&
(z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) {
@@ -939,14 +939,15 @@ static void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval
*va
}
ZVAL_COPY_VALUE(z, value);
}
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT_P(object)->write_dimension(object, property, z);
+ binary_op(&res, Z_ISREF_P(z) ? Z_REFVAL_P(z) : z, value);
+ Z_OBJ_HT_P(object)->write_dimension(object, property, &res);
+ if (z == &rv) {
+ zval_ptr_dtor(&rv);
+ }
if (retval) {
- ZVAL_COPY(retval, z);
+ ZVAL_COPY(retval, &res);
}
- zval_ptr_dtor(z);
+ zval_ptr_dtor(&res);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
if (retval) {