Skip to content

Commit 41ae8de

Browse files
committed
Fixed bug #39297 (Memory corryption because of indirect modification of overloaded array).
1 parent a84a2ea commit 41ae8de

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ PHP NEWS
3030
an extension INI directive). (wharmby at uk dot ibm dot com, Dmitry)
3131
- Fixed bug #39320 (ZEND_HASH_APPLY_STOP causes deletion). (Marcus)
3232
- Fixed bug #39313 (spl_autoload triggers Fatal error). (Marcus)
33+
- Fixed bug #39297 (Memory corryption because of indirect modification
34+
of overloaded array). (Dmitry)
3335
- Fixed bug #39265 (Fixed path handling inside mod_files.sh).
3436
(michal dot taborsky at gmail dot com, Ilia)
3537
- Fixed bug #39215 (Inappropriate close of stdin/stdout/stderr). (Wez,Ilia)

Zend/tests/bug39297.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Bug #39297 (Memory corryption because of indirect modification of overloaded array)
3+
--FILE--
4+
<?php
5+
function compareByRef(&$first, &$second) {
6+
return $first === $second;
7+
}
8+
9+
class MyTree implements ArrayAccess {
10+
public $parent;
11+
public $children = array();
12+
13+
public function offsetExists($offset) {
14+
}
15+
16+
public function offsetUnset($offset) {
17+
}
18+
19+
public function offsetSet($offset, $value) {
20+
echo "offsetSet()\n";
21+
$cannonicalName = strtolower($offset);
22+
$this->children[$cannonicalName] = $value;
23+
$value->parent = $this;
24+
}
25+
26+
public function offsetGet($offset) {
27+
echo "offsetGet()\n";
28+
$cannonicalName = strtolower($offset);
29+
return $this->children[$cannonicalName];
30+
}
31+
32+
}
33+
34+
$id = 'Test';
35+
36+
$root = new MyTree();
37+
$child = new MyTree();
38+
$root[$id] = $child;
39+
40+
var_dump(compareByRef($root[$id], $child));
41+
?>
42+
--EXPECT--
43+
offsetSet()
44+
offsetGet()
45+
bool(true)

Zend/zend_object_handlers.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,19 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
469469
/* Undo PZVAL_LOCK() */
470470
retval->refcount--;
471471

472+
if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && retval->refcount > 0) {
473+
zval *tmp = retval;
474+
475+
ALLOC_ZVAL(retval);
476+
*retval = *tmp;
477+
zval_copy_ctor(retval);
478+
retval->is_ref = 0;
479+
retval->refcount = 0;
480+
if (Z_TYPE_P(retval) != IS_OBJECT) {
481+
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
482+
}
483+
}
484+
472485
return retval;
473486
} else {
474487
zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);

0 commit comments

Comments
 (0)