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);
|
zval *zv = zend_hash_index_find(&wm->ht, (zend_ulong) obj_key);
|
||||||
if (zv) {
|
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_COPY_VALUE(zv, value);
|
||||||
|
zval_ptr_dtor(&zv_orig);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user