mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
Fix use after free when WeakMap is modified during field write
(When a value's destructor triggers a resizing or rehashing of the WeakMap) Closes GH-7671
This commit is contained in:
parent
2f8407f185
commit
241bd3f454
116
Zend/tests/weakrefs/weakrefs_006.phpt
Normal file
116
Zend/tests/weakrefs/weakrefs_006.phpt
Normal file
@ -0,0 +1,116 @@
|
||||
--TEST--
|
||||
WeakReference overwriting existing value
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class HasDtor {
|
||||
public function __destruct() {
|
||||
echo "In destruct\n";
|
||||
global $w, $all;
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$v = new stdClass();
|
||||
$all[] = $v;
|
||||
$w[$v] = $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
$all = [];
|
||||
$w = new WeakMap();
|
||||
$o = new stdClass();
|
||||
|
||||
$w[$o] = new HasDtor();
|
||||
$w[$o] = 123;
|
||||
var_dump($w);
|
||||
?>
|
||||
--EXPECT--
|
||||
In destruct
|
||||
object(WeakMap)#1 (11) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#2 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(123)
|
||||
}
|
||||
[1]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#4 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(0)
|
||||
}
|
||||
[2]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#5 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(1)
|
||||
}
|
||||
[3]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#6 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(2)
|
||||
}
|
||||
[4]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#7 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(3)
|
||||
}
|
||||
[5]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#8 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(4)
|
||||
}
|
||||
[6]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#9 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(5)
|
||||
}
|
||||
[7]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#10 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(6)
|
||||
}
|
||||
[8]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#11 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(7)
|
||||
}
|
||||
[9]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#12 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(8)
|
||||
}
|
||||
[10]=>
|
||||
array(2) {
|
||||
["key"]=>
|
||||
object(stdClass)#13 (0) {
|
||||
}
|
||||
["value"]=>
|
||||
int(9)
|
||||
}
|
||||
}
|
@ -351,8 +351,12 @@ static void zend_weakmap_write_dimension(zend_object *object, zval *offset, zval
|
||||
|
||||
zval *zv = zend_hash_index_find(&wm->ht, (zend_ulong) obj_key);
|
||||
if (zv) {
|
||||
zval_ptr_dtor(zv);
|
||||
/* Because the destructors can have side effects such as resizing or rehashing the WeakMap storage,
|
||||
* free the zval only after overwriting the original value. */
|
||||
zval zv_orig;
|
||||
ZVAL_COPY_VALUE(&zv_orig, zv);
|
||||
ZVAL_COPY_VALUE(zv, value);
|
||||
zval_ptr_dtor(&zv_orig);
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user