[php-src] Issue #13612: Corrupted memory in destructor with weak references

From: Date: Wed, 06 Mar 2024 22:02:30 +0000
Subject: [php-src] Issue #13612: Corrupted memory in destructor with weak references
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-246524@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/13612 Author: mvorisek ### Description In the code below, var_dump(array_keys($analysingMap->valueWithOwnerCountByIndex)) called twice prints different results even if the value is not changed between the calls. I did my best to create a minimal repro. It seems the issue is present when weak references and destructor are used. When opcache and/or GC is disabled, the issue is still present. It seems there is some allocation/refcounting issue in destructors. repro: https://3v4l.org/h7ZER ```php <?php class WeakMap2 { private array $weakRefs = []; private array $values = []; public function offsetSet($object, $value) : void { $id = spl_object_id($object); $this->weakRefs[$id] = \WeakReference::create($object); $this->values[$id] = $value; } } class WeakAnalysingMapRepro { /* private */ public array $valueWithOwnerCountByIndex = []; private WeakMap2 $ownerDestructorHandlers; public function __construct() { $this->ownerDestructorHandlers = new WeakMap2(); $this->addKeyOwner(new \DateTime()); } protected function addKeyOwner(object $owner) { $handler = new class($this) { private \WeakReference $weakAnalysingMap; public function __construct(WeakAnalysingMapRepro $analysingMap) { $this->weakAnalysingMap = \WeakReference::create($analysingMap); } public function __destruct() { $analysingMap = $this->weakAnalysingMap->get(); var_dump(array_keys($analysingMap->valueWithOwnerCountByIndex)); \Closure::bind(static function () use ($analysingMap) { var_dump(array_keys($analysingMap->valueWithOwnerCountByIndex)); }, null, WeakAnalysingMapRepro::class)(); } public function addReference($index): void { $analysingMap = $this->weakAnalysingMap->get(); $analysingMap->valueWithOwnerCountByIndex[$index] = true; } }; $this->ownerDestructorHandlers->offsetSet($owner, $handler); $handler->addReference(10); } } $map = new WeakAnalysingMapRepro(); unset($map); echo 'DONE'; ``` Resulted in this output: ``` array(1) { [0]=> int(10) } array(1) { [0]=> string(12) "analysingMap" } DONE ``` But I expected this output instead: ``` array(1) { [0]=> int(10) } array(1) { [0]=> int(10) } DONE ``` ### PHP Version 7.4 - master ### Operating System Windows, Linux

« previous php.bugs (#246524) next »