[php-src] Issue #13687: Method call may leak if releasing EG(This) triggers GC
| From: | arnaud-lb | Date: | Tue, 12 Mar 2024 18:13:43 +0000 |
| Subject: | [php-src] Issue #13687: Method call may leak if releasing EG(This) triggers GC | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-246571@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/13687
Author: arnaud-lb
### Description
Method calls may cause their return value to leak if releasing EG(This) triggers GC.
The following code:
```php
<?php
class A {
public $cycle;
public function __construct() { $this->cycle = $this; }
}
class B {
public function get() {
return new A();
}
}
$c = new B();
$objs = [];
while (gc_status()['roots']+2 < gc_status()['threshold']) {
$obj = new stdClass;
$objs[] = $obj;
}
var_dump($c->get());
```
Resulted in a memory leak:
```
Script: 'test.php'
Zend/zend_objects.c(189) : Freeing 0x00007ffff7a5c840 (56 bytes), script=test.php
=== Total 1 memory leaks detected ===
```
Here is what is happening:
- After returning from
get(), [$c is
released](https://github.com/php/php-src/blob/94a12d5b315aa73a24b96cfebb4fd38b8e9b800e/Zend/zend_vm_def.h#L2866),
which triggers GC
- A is removed from buffer, and is not collected because it's referenced by the
call stack
- After returning from var_dump(),
[zend_vm_stack_free_args()](https://github.com/php/php-src/blob/94a12d5b315aa73a24b96cfebb4fd38b8e9b800e/Zend/zend_vm_def.h#L4019)
releases A with zval_ptr_dtor_nogc(), so A is not added to
the GC buffer
- At this point nothing references A but itself, and A is not in the GC
buffer, so it leaks
I'm not sure how to fix this appart from switching to zval_ptr_dtor().
### PHP Version
master
### Operating System
_No response_