php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66091 Memory leak in DateTime::createFromFormat()
Submitted: 2013-11-13 17:01 UTC Modified: 2014-04-06 13:00 UTC
Votes:7
Avg. Score:4.4 ± 0.9
Reproduced:7 of 7 (100.0%)
Same Version:6 (85.7%)
Same OS:7 (100.0%)
From: lars_teuber at gmx dot de Assigned: ab
Status: Closed Package: Unknown/Other Function
PHP Version: Irrelevant OS: Windows/Linux
Private report: No CVE-ID:
 [2013-11-13 17:01 UTC] lars_teuber at gmx dot de
Description:
------------
Hi,

DateTime::createFromFormat() has a memory leak.

Tested with: 5.3.14, 5.4.4, 5.5.3

Best regards
Lars Teuber

Test script:
---------------
<?php
$mem_start = memory_get_usage(true);
echo 'start: ' . $mem_start . '<br>';

$max_iterations = 1000000;
for ($i = 1; $i <= $max_iterations; $i++) {
    DateTime::createFromFormat('M/D/Y H:i:s', '2013-11-12 20:00:00');
    if (($i % 100000) == 0) {
        echo $i . '.: ' . memory_get_usage(true) . '<br>';
    }
}
$mem_end = memory_get_usage(true);
echo 'end: ' . $mem_end . '<br>';
echo 'diff end-start: ' . ($mem_end - $mem_start) . '<br>';
?>

Expected result:
----------------
(more or less) constant memory usage

Actual result:
--------------
start:             524288
100000.:         16777216
200000.:         33030144
300000.:         53477376
400000.:         65536000
500000.:         77594624
600000.:        106168320
700000.:        118226944
800000.:        130285568
900000.:        142344192
1000000.:       154140672
end:            154140672
diff end-start: 153616384

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-04-05 17:03 UTC] ab@php.net
But in your code, you just continuously create new objects. It is then logic that the memory is cluttered up. Try using the return value and then explicitly unset() it.
 [2014-04-05 17:03 UTC] ab@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: ab
 [2014-04-05 17:03 UTC] ab@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

so marking as nab
 [2014-04-05 19:53 UTC] nikic@php.net
@ab: If you don't use the return value of a function call, it will be immidiately destroyed. As such there should be no difference between ignoring the return value and doing an assing+unset. To me this looks like we're indeed leaking something.
 [2014-04-06 13:00 UTC] ab@php.net
-Status: Not a bug +Status: Assigned
 [2014-04-06 13:00 UTC] ab@php.net
@nikic, now looking at the code of date_load_from_format i think you're right. In case it has to RETURN_FALSE a leak is possible. I will check that, thanks.
 [2014-07-18 04:31 UTC] nurlan0000 at gmail dot com
@ab, It's been almost a year since the bug was reported. Any updates on this?
 [2014-07-18 05:07 UTC] nurlan0000 at gmail dot com
Here's the valgrind output for test.php:

for ( $i = 0; $i < 100000; $i++ ) {
    $d = DateTime::createFromFormat('m-d-Y', '05-21-2014');
    unset($d);
}

valgrind --leak-check=yes --leak-check=full --show-leak-kinds=all php test.php


==21278== 5,922 bytes in 416 blocks are still reachable in loss record 14 of 18
==21278==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21278==    by 0x698C679: strdup (strdup.c:42)
==21278==    by 0x48BCB4: ??? (in /usr/bin/php5)
==21278==    by 0x48C164: timelib_builtin_db (in /usr/bin/php5)
==21278==    by 0x46D1CC: php_date_initialize (in /usr/bin/php5)
==21278==    by 0x46D41D: zif_date_create_from_format (in /usr/bin/php5)
==21278==    by 0x6DD6BA: dtrace_execute_internal (in /usr/bin/php5)
==21278==    by 0x79D714: ??? (in /usr/bin/php5)
==21278==    by 0x717447: execute_ex (in /usr/bin/php5)
==21278==    by 0x6DD5B8: dtrace_execute_ex (in /usr/bin/php5)
==21278==    by 0x6EF03F: zend_execute_scripts (in /usr/bin/php5)
==21278==    by 0x68EF24: php_execute_script (in /usr/bin/php5)
==21278== 
==21278== 8,168 bytes in 1 blocks are still reachable in loss record 15 of 18
==21278==    at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21278==    by 0x48BB48: ??? (in /usr/bin/php5)
==21278==    by 0x48C164: timelib_builtin_db (in /usr/bin/php5)
==21278==    by 0x46D1CC: php_date_initialize (in /usr/bin/php5)
==21278==    by 0x46D41D: zif_date_create_from_format (in /usr/bin/php5)
==21278==    by 0x6DD6BA: dtrace_execute_internal (in /usr/bin/php5)
==21278==    by 0x79D714: ??? (in /usr/bin/php5)
==21278==    by 0x717447: execute_ex (in /usr/bin/php5)
==21278==    by 0x6DD5B8: dtrace_execute_ex (in /usr/bin/php5)
==21278==    by 0x6EF03F: zend_execute_scripts (in /usr/bin/php5)
==21278==    by 0x68EF24: php_execute_script (in /usr/bin/php5)
==21278==    by 0x79F6ED: ??? (in /usr/bin/php5)
==21278== 
==21278== 9,029 bytes in 594 blocks are still reachable in loss record 16 of 18
==21278==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21278==    by 0x698C679: strdup (strdup.c:42)
==21278==    by 0x48B994: ??? (in /usr/bin/php5)
==21278==    by 0x48C15F: timelib_builtin_db (in /usr/bin/php5)
==21278==    by 0x46D1CC: php_date_initialize (in /usr/bin/php5)
==21278==    by 0x46D41D: zif_date_create_from_format (in /usr/bin/php5)
==21278==    by 0x6DD6BA: dtrace_execute_internal (in /usr/bin/php5)
==21278==    by 0x79D714: ??? (in /usr/bin/php5)
==21278==    by 0x717447: execute_ex (in /usr/bin/php5)
==21278==    by 0x6DD5B8: dtrace_execute_ex (in /usr/bin/php5)
==21278==    by 0x6EF03F: zend_execute_scripts (in /usr/bin/php5)
==21278==    by 0x68EF24: php_execute_script (in /usr/bin/php5)
==21278== 
==21278== 16,384 bytes in 1 blocks are still reachable in loss record 17 of 18
==21278==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21278==    by 0x48BA89: ??? (in /usr/bin/php5)
==21278==    by 0x48C15F: timelib_builtin_db (in /usr/bin/php5)
==21278==    by 0x46D1CC: php_date_initialize (in /usr/bin/php5)
==21278==    by 0x46D41D: zif_date_create_from_format (in /usr/bin/php5)
==21278==    by 0x6DD6BA: dtrace_execute_internal (in /usr/bin/php5)
==21278==    by 0x79D714: ??? (in /usr/bin/php5)
==21278==    by 0x717447: execute_ex (in /usr/bin/php5)
==21278==    by 0x6DD5B8: dtrace_execute_ex (in /usr/bin/php5)
==21278==    by 0x6EF03F: zend_execute_scripts (in /usr/bin/php5)
==21278==    by 0x68EF24: php_execute_script (in /usr/bin/php5)
==21278==    by 0x79F6ED: ??? (in /usr/bin/php5)
==21278== 
==21278== 43,264 bytes in 416 blocks are still reachable in loss record 18 of 18
==21278==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21278==    by 0x48BC85: ??? (in /usr/bin/php5)
==21278==    by 0x48C164: timelib_builtin_db (in /usr/bin/php5)
==21278==    by 0x46D1CC: php_date_initialize (in /usr/bin/php5)
==21278==    by 0x46D41D: zif_date_create_from_format (in /usr/bin/php5)
==21278==    by 0x6DD6BA: dtrace_execute_internal (in /usr/bin/php5)
==21278==    by 0x79D714: ??? (in /usr/bin/php5)
==21278==    by 0x717447: execute_ex (in /usr/bin/php5)
==21278==    by 0x6DD5B8: dtrace_execute_ex (in /usr/bin/php5)
==21278==    by 0x6EF03F: zend_execute_scripts (in /usr/bin/php5)
==21278==    by 0x68EF24: php_execute_script (in /usr/bin/php5)
==21278==    by 0x79F6ED: ??? (in /usr/bin/php5)
 [2014-07-18 05:25 UTC] nurlan0000 at gmail dot com
I think I've found situation when the memory leak occurs. 
Memory is leaked only when you try to parse invalid date.
Here's example script:

for ( $i = 0; $i < 10000; $i++ ) {
    $d = DateTime::createFromFormat('m-d-Y', 'asdf asdf');
    unset($d);
    
    if ($i % 100 == 0) {
        echo 'Memory usage: ', memory_get_usage(), PHP_EOL;
    }
}
 [2014-08-09 14:36 UTC] nurlan0000 at gmail dot com
[PATCH] I've submitted a patch here - https://github.com/php/php-src/pull/766
 [2014-08-13 12:28 UTC] datibbaw@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=f6896e4395e89ceeacd8f8a940cbafeeee3ac4a3
Log: Fixed #66091
 [2014-08-13 12:28 UTC] datibbaw@php.net
-Status: Assigned +Status: Closed
 [2014-08-13 12:28 UTC] datibbaw@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=4b85f1d46ad90ba8b31e4f961bd84c3e6fa0f0bf
Log: Fixed #66091
 [2014-08-14 00:52 UTC] tyrael@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=f6896e4395e89ceeacd8f8a940cbafeeee3ac4a3
Log: Fixed #66091
 [2014-08-14 15:34 UTC] johannes@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=f6896e4395e89ceeacd8f8a940cbafeeee3ac4a3
Log: Fixed #66091
 [2014-08-14 15:34 UTC] johannes@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=4b85f1d46ad90ba8b31e4f961bd84c3e6fa0f0bf
Log: Fixed #66091
 [2014-08-14 19:32 UTC] dmitry@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=4b85f1d46ad90ba8b31e4f961bd84c3e6fa0f0bf
Log: Fixed #66091
 [2014-08-14 19:32 UTC] dmitry@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src.git;a=commit;h=f6896e4395e89ceeacd8f8a940cbafeeee3ac4a3
Log: Fixed #66091
 [2014-10-07 23:13 UTC] stas@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src-security.git;a=commit;h=f6896e4395e89ceeacd8f8a940cbafeeee3ac4a3
Log: Fixed #66091
 [2014-10-07 23:24 UTC] stas@php.net
Automatic comment on behalf of datibbaw
Revision: http://git.php.net/?p=php-src-security.git;a=commit;h=f6896e4395e89ceeacd8f8a940cbafeeee3ac4a3
Log: Fixed #66091
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Wed Feb 22 22:01:36 2017 UTC