php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81251 Memory leak with datetime, serialization, and require
Submitted: 2021-07-12 10:05 UTC Modified: 2021-07-12 13:04 UTC
From: lyrixx at lyrixx dot info Assigned: cmb (profile)
Status: Wont fix Package: Variables related
PHP Version: 8.0.8 OS: linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: lyrixx at lyrixx dot info
New email:
PHP Version: OS:

 

 [2021-07-12 10:05 UTC] lyrixx at lyrixx dot info
Description:
------------
When one require a PHP script, that unserialize some data with an instance of DateTime in it, a memory leak occurs 

Test script:
---------------
<?php

class Foobar
{
    public function __construct(
        // If this property is removed => No leak
        public DateTime $d,
    ) {
    }
}

for ($i=0; $i < 10000; $i++) {
    $foobar = new Foobar(new \DateTime());

    // 1. Leak when "require" is involved
    $file = '/tmp/test-serialized.php';
    file_put_contents($file, sprintf("<?php return unserialize(base64_decode('%s'));\n", base64_encode(serialize($foobar))));
    $o = require $file;

    // 2. No leak in this case
    // unserialize(serialize($foobar));

    if ($i % 1000 === 0) {
        printf("%.2fMb\n", memory_get_usage() / 1024 / 1024);
    }
}

Expected result:
----------------
0.38Mb
0.38Mb
0.38Mb
0.38Mb
0.38Mb
0.38Mb
0.38Mb
0.38Mb
0.38Mb
0.38Mb


Actual result:
--------------
0.38Mb
0.66Mb
0.90Mb
1.23Mb
1.47Mb
1.87Mb
2.11Mb
2.36Mb
2.60Mb
3.16Mb

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-07-12 12:43 UTC] cmb@php.net
-Status: Open +Status: Duplicate -Package: *General Issues +Package: Variables related -Assigned To: +Assigned To: cmb
 [2021-07-12 12:43 UTC] cmb@php.net
This reproduces on PHP-7.4 as well, and is because the different
serialized strings are all interned; see bug #81142.
 [2021-07-12 12:52 UTC] lyrixx at lyrixx dot info
Thanks for the comment.

BTW, I noticed that :

php test.php
=> Memory leak

php -n test.php
=> Memory leak

php -n -d zend_extension=opcache -d "opcache.enable_cli=on"  test.php
=> NO memory leak !

This is a bit crazy to me.

Anyway, I fail to see why the relation with bug #81142. There is **no array** in my case.
More over, as I noticed in the initial bug report, if the code don't goes through "require", 
there is not memory leak. So "unserialize(serialize($foobar))" doesn't leak in my case.
 [2021-07-12 13:04 UTC] nikic@php.net
-Status: Duplicate +Status: Wont fix
 [2021-07-12 13:04 UTC] nikic@php.net
This isn't the same issue as bug #81142. There the unserialize() implementation itself interns some strings. It shouldn't be going that, because the strings are potentially runtime-derived. Here you are creating PHP files with distinct string literals (there isn't any particular relation to unserialize -- you're just creating different strings through it, thanks to microseconds on DateTime). These should get interned, as they are compile-time constants strings as far as PHP is concerned. We will not change this behavior.

The same happens with opcache, but the strings will be in shared memory, so it will be part of opcache's memory usage, not memory_get_usage().
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Sat Sep 25 00:03:42 2021 UTC