diff --git a/Zend/tests/bug39297.phpt b/Zend/tests/bug39297.phpt new file mode 100755 index 00000000000..92f91a55571 --- /dev/null +++ b/Zend/tests/bug39297.phpt @@ -0,0 +1,45 @@ +--TEST-- +Bug #39297 (Memory corryption because of indirect modification of overloaded array) +--FILE-- +children[$cannonicalName] = $value; + $value->parent = $this; + } + + public function offsetGet($offset) { + echo "offsetGet()\n"; + $cannonicalName = strtolower($offset); + return $this->children[$cannonicalName]; + } + +} + +$id = 'Test'; + +$root = new MyTree(); +$child = new MyTree(); +$root[$id] = $child; + +var_dump(compareByRef($root[$id], $child)); +?> +--EXPECT-- +offsetSet() +offsetGet() +bool(true) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 79e64b25428..03953182ea1 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -477,6 +477,19 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* Undo PZVAL_LOCK() */ retval->refcount--; + if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && retval->refcount > 0) { + zval *tmp = retval; + + ALLOC_ZVAL(retval); + *retval = *tmp; + zval_copy_ctor(retval); + retval->is_ref = 0; + retval->refcount = 0; + if (Z_TYPE_P(retval) != IS_OBJECT) { + zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name); + } + } + return retval; } else { zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);