php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #57692 Double free when returning cached object with __sleep
Submitted: 2007-06-04 10:32 UTC Modified: 2007-06-04 15:40 UTC
From: Sjon at parse dot nl Assigned: tony2001 (profile)
Status: Closed Package: memcache (PECL)
PHP Version: 4.4.5 OS: Linux
Private report: No CVE-ID: None
 [2007-06-04 10:32 UTC] Sjon at parse dot nl
Description:
------------
The memcache-serialization code makes the php code double free memory; which causes a crash. Serializing 'by hand' or when $block is not returned the bug can be avoided

Reproduce code:
---------------
class block
{
        var $waa = 'meukee';
        function __sleep() { return array('waa'); }
}

function cache_failure()
{
        $block = new block();
        $GLOBALS['cache']->set('block', $block);

        return $block;
}

$cache = new memcache;
$cache->connect('localhost', '11211');

cache_failure();


Expected result:
----------------
No double-free crash

Actual result:
--------------
Breakpoint 2 at 0x40803c81
(gdb) bt  
#0  0x40803c81 in kill () from /lib/libc.so.6
#1  0x408038e5 in raise () from /lib/libc.so.6
#2  0x40804f00 in abort () from /lib/libc.so.6
#3  0x408376ce in __libc_message () from /lib/libc.so.6
#4  0x4083dcae in _int_free () from /lib/libc.so.6
#5  0x4083e076 in free () from /lib/libc.so.6
#6  0x081c741d in shutdown_memory_manager (silent=0, clean_cache=0) at /usr/src/php-4.4.7/Zend/zend_alloc.c:514
#7  0x081a9d73 in php_request_shutdown (dummy=0x0) at /usr/src/php-4.4.7/main/main.c:1015
#8  0x081ef4e3 in main (argc=2, argv=0xbfffe644) at /usr/src/php-4.4.7/sapi/cli/php_cli.c:889


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-06-04 14:15 UTC] mikael at synd dot info
Was able to reproduce this problem with 4.4.6 and 2.1.2, static build. When debug symbols disabled I get core dump but with debug symbols on, I get memory leak instead.

As far as I can see, the call to php_var_serialize() is identical between php_mmc_store() and PHP_FUNCTION(serialize). When not using __sleep() the refcount of the var is 2 and is_ref == 0 both before and after the call to php_var_serialize(), but when using __sleep() the refcount is decremented to 1 and is_ref set to 1 (using Eclipse+CDT makes this very visible.) 

This behavior is the same with both php_mmc_store() and serialize() so why we get a coredump in the first case and not the second beats me, the only difference being the use of zend_parse_parameters() over zend_get_parameters_ex(). 

Could not reproduce with PHP 5.2.2

Anthony, have any ideas? Think this might be beyond my current level of knowledge about the PHP internals..

//Mikael


Memory leak output:

/home/mikl/arch/php4/src/php-4.4.6/Zend/zend_hash.c(280) :  Freeing 0x082F6DC4 (39 bytes), script=/home/mikl/arch/php4/src/php-4.4.6/ext/memcache/tests/001.php
/home/mikl/arch/php4/src/php-4.4.6/Zend/zend_hash.c(204) :  Freeing 0x082F6D74 (32 bytes), script=/home/mikl/arch/php4/src/php-4.4.6/ext/memcache/tests/001.php
/home/mikl/arch/php4/src/php-4.4.6/Zend/zend_execute.c(276) :  Freeing 0x082F6D14 (44 bytes), script=/home/mikl/arch/php4/src/php-4.4.6/ext/memcache/tests/001.php
/home/mikl/arch/php4/src/php-4.4.6/Zend/zend_variables.c(138) : Actual location (location was relayed)
/home/mikl/arch/php4/src/php-4.4.6/Zend/zend_execute.c(273) :  Freeing 0x082F88FC (12 bytes), script=/home/mikl/arch/php4/src/php-4.4.6/ext/memcache/tests/001.php
/home/mikl/arch/php4/src/php-4.4.6/Zend/zend_compile.c(1703) :  Freeing 0x082F973C (12 bytes), script=/home/mikl/arch/php4/src/php-4.4.6/ext/memcache/tests/001.php
Zend/zend_language_scanner.c(4673) :  Freeing 0x082F9704 (4 bytes), script=/home/mikl/arch/php4/src/php-4.4.6/ext/memcache/tests/001.php
 [2007-06-04 15:40 UTC] tony2001 at phpclub dot net
This bug has been fixed in CVS.

In case this was a documentation problem, the fix will show up at the
end of next Sunday (CET) on pecl.php.net.

In case this was a pecl.php.net website problem, the change will show
up on the website in short time.
 
Thank you for the report, and for helping us make PECL better.

It seems to be somehow related to this patch:
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/var.c?r1=1.249&r2=1.250
(I didn't merge it to PHP4, it's not a security fix).

Fixed in CVS.
 [2007-06-07 07:23 UTC] hans at parse dot nl
Wanting to fix this issue in PHP4, i've backported that patch to php4. This fixes the issue with the testcase in this bugreport, but opens up a new issue when using a regular serialize call. It turns the problem around so to say.

My patch against php-4.4.7 var.c is at http://home.parse.nl/~hans/temp/serializer_php4_patch.diff

Running the patched php against the testcase above results in proper refcounts(2) and is_ref(0) before and after the call to php_var_serialize().

Now take the following testcase:

<?php
class block
{
        var $test = 'waa';

        function __sleep() { return array('test'); }
}

$block = new block();
$block=serialize($block);
echo $block;
?>

Running this with original php-4.4.7 works as expected, with refcount=2 is_ref=0 before, and refcount=1 is_ref=1 after the call to php_var_serialize()

Running this with patched php-4.4.7 results in a double free in shutdown_memory_manager, with refcount=2 is_ref=0 before, and refcount=1 is_ref=0 after the call to php_var_serialize()

The alterations to refcount and is_ref happen in the ZE function call_user_function_ex() which executes the user __sleep function.

I'm kinda lost in searching for the cause of this problem, but it is clear that the changes that tony2001 refers to solve the initial problem, but create another. If anyone can give me some pointers, it will be much appreciated. Would be nice if we can get this fixed with php4 (although i know that the Zend guys really want us to upgrade ;) but that is not an option for us at the moment)

Thanks
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 16 04:01:27 2024 UTC