php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48541 spl_autoload_register only registers first closure, then leaks the others
Submitted: 2009-06-13 06:09 UTC Modified: 2009-06-13 18:07 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: cellog@php.net Assigned: cellog (profile)
Status: Closed Package: SPL related
PHP Version: 5.3CVS-2009-06-13 (CVS) OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: cellog@php.net
New email:
PHP Version: OS:

 

 [2009-06-13 06:09 UTC] cellog@php.net
Description:
------------
The test script below does not leak, but if $a were to successfully load class "foo" (i.e. move the eval() in $b() into $a) it leaks memory in zend_execute.c on line 723, which is the portion called when the closure is assigned to $b.

This is caused by 2 separate bugs.

1) php_spl.c line 501 increases the refcount of the closure zval
2) php_spl.c line 511 checks to see if the function name has already been registered, but treats all closures as if they were "closure::__invoke" instead of using some unique aspect of each closure.  This then jumps to the end of spl_autoload_register without decreasing the refcount, and boom, we have a memory leak.

I don't know anything about the closures implementation, so someone who knows a better way to get a unique function name for a closure needs to fix this, both the refcount and the only-one-closure-allowed issues.

Also, the memory leak is triggered by an important feature of Pyrus, and yes, we are registering multiple closures as autoload callbacks to implement a dynamic plugin system.  It works great except for these two bugs.

Reproduce code:
---------------
<?php
$a = function ($class) {
    echo "a called\n";
};
$b = function ($class) {
    eval('class ' . $class . '{}');
    echo "b called\n";
};
spl_autoload_register($a);
spl_autoload_register($b);
$c = new foo;


Expected result:
----------------
a called
b called

Actual result:
--------------
a called

Fatal error: Class 'foo' not found in /home/user/workspace/php5/test.php on line 11

Call Stack:
    0.0005     345172   1. {main}() /home/user/workspace/php5/test.php:0



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-06-13 18:07 UTC] cellog@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

fixed in HEAD and PHP_5_3
 [2010-04-27 15:31 UTC] dmitry@php.net
Automatic comment from SVN on behalf of dmitry
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=298660
Log: Fixed memory leak in ext/spl/tests/spl_autoload_bug48541.phpt
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Nov 25 15:01:32 2024 UTC