Bug #74802 [NEW]: Bogus detection of values capture in destructors within garbage collector
| From: | bwoebi@php.net | Date: | Fri, 23 Jun 2017 02:45:03 +0000 |
| Subject: | Bug #74802 [NEW]: Bogus detection of values capture in destructors within garbage collector | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-209637@lists.php.net to get a copy of this message | ||
From: bwoebi
Operating system: Irrelevant
PHP version: master-Git-2017-06-23 (Git)
Package: Reproducible crash
Bug Type: Bug
Bug description:Bogus detection of values capture in destructors within garbage collector
Description:
------------
Our current logic in garbage collector assumes that, if we have a
refcount not higher than before, the data can be safely freed.
Which is not a valid assumption as the following snippet demonstrates:
if the value is incremented by backing up and decremented again by
manual unset(), the refcount is still equal; thus the garbage collector
will free it, even though it cannot.
The relevant snippet within zend_gc.c, after invoking destructors, on
each remaining root:
if (GC_REFCOUNT(current->ref) > current->refcount) {
gc_remove_nested_data_from_buffer(current->ref, current);
}
Test script:
---------------
(function() {
$foo = new class {
public $bar;
function __destruct() {
global $bak;
$bak = $this->bar;
unset($this->bar); // do not fulfil the
condition
}
};
$bar = new stdClass;
$bar->foo = $foo;
$foo->bar = $bar;
})();
gc_collect_cycles();
var_dump($bak);
Expected result:
----------------
object(stdClass)#3 (1) {
["foo"]=>
object(class@anonymous)#2 (1) {
["bar"]=>
*RECURSION*
}
}
Actual result:
--------------
Segmentation fault (or at least valgrind warning)
--
Edit bug report at https://bugs.php.net/bug.php?id=74802&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=74802&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=74802&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=74802&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=74802&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=74802&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=74802&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=74802&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=74802&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=74802&r=support
Expected behavior: https://bugs.php.net/fix.php?id=74802&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=74802&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=74802&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=74802&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=74802&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=74802&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=74802&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=74802&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=74802&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=74802&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=74802&r=mysqlcfg