|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2017-01-19 18:05 UTC] highmind63 at gmail dot com
Description:
------------
Memory leaks with referenced variable return in static method called by instance method.
Test script:
---------------
<pre>
<?php
class Leak {
static protected function &leaked(array &$array = null) {
$array = array('one');
return $array;
}
public function toLeaked($array = null) {
$array = static::leaked($array);
return $array;
}
public function testLeak() {
echo "memory before loop: " . memory_get_usage(true) . PHP_EOL;
for ($i = 0; $i < 5000; $i++) {
$leak = $this->toLeaked();
}
echo "memory after loop: " . memory_get_usage(true) . PHP_EOL;
}
}
$leak = new Leak();
$leak->testLeak();
?>
</pre>
Expected result:
----------------
No Leak
Actual result:
--------------
Leaks Memory:
memory before loop: 2097152
memory after loop: 4194304
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 17:00:01 2025 UTC |
Reduced testcase: function &leaked(array &$array = null) { $array = array('one'); return $array; } $array = leaked($array);Even simpler repro: $array = array('one'); $array = $ref =& $array; The problem is that in zend_assign_to_variable() in the case where LHS and RHS point to the same value we currently do not destroy the RHS if it is a VAR. Proposed patch: diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 554ad28..5f0caf6 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -81,6 +81,10 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval return variable_ptr; } if (ZEND_CONST_COND(value_type & (IS_VAR|IS_CV), 1) && variable_ptr == value) { + if (value_type == IS_VAR && ref) { + ZEND_ASSERT(GC_REFCOUNT(ref) > 1); + --GC_REFCOUNT(ref); + } return variable_ptr; } garbage = Z_COUNTED_P(variable_ptr);