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
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:2 (100.0%)
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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
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().
 [2023-06-26 08:05 UTC] gerefo6485 at aramask dot com
Nice Article here good one.



(https://www.librarygenesis.xyz)php.net
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 16 05:01:29 2024 UTC