php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47285 strtotime() still leaks memory
Submitted: 2009-02-03 01:19 UTC Modified: 2009-09-02 11:52 UTC
Votes:34
Avg. Score:4.6 ± 0.9
Reproduced:30 of 31 (96.8%)
Same Version:23 (76.7%)
Same OS:21 (70.0%)
From: danger at FreeBSD dot org Assigned: derick
Status: Assigned Package: Date/time related
PHP Version: 5.2 (SVN-2009-0-02) OS: *
Private report: No CVE-ID:
Have you experienced this issue?
Rate the importance of this bug to you:

 [2009-02-03 01:19 UTC] danger at FreeBSD dot org
Description:
------------
The strtotime() function still leaks memory in patched PHP 5.2.8 after applying patches from http://news.php.net/php.cvs/55000. The memory leak itself is much smaller than before applying fixes. Before, it took a few seconds to leak 1gb of mem, now it takes some minutes however it's still there.

This bug is related to http://bugs.php.net/bug.php?id=46889.

Reproduce code:
---------------
while (true)
{
   $tmp = inc_stamp(time(), 1);
}

function inc_stamp($timestamp, $off_days)
{
   return strtotime("+" . $off_days . " day", $timestamp);
}

Actual result:
--------------
Memory leak reported by top(1). If the script runs for longer time, it gets killed by kernel since the system is going out of memory and swap.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-02-05 09:56 UTC] danger at FreeBSD dot org
root@[web1 ~]# php -v
PHP 5.2.9-dev (cli) (built: Feb  5 2009 10:52:28)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
    with XCache v1.2.2, Copyright (c) 2005-2007, by mOo

I also applied distribution patches that come with FreeBSD (exluding the patch-ext_date_lib_timelib_structs.h one), you may find them at http://cvsweb.freebsd.org/ports/lang/php5/files.

Verified that the above PHP version still leaks memory, slower but still.
 [2009-02-05 10:01 UTC] derick@php.net
Like I said, I can not reproduce this. But please test without xcache being loaded!
 [2009-02-05 12:09 UTC] danger at FreeBSD dot org
root@[temp ~]# php -v
PHP 5.2.9-dev (cli) (built: Feb  5 2009 13:04:42)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

still leaks. If you are interested in access to that box to debug, I will be glad to provide you with the login credentials.
 [2009-02-13 11:02 UTC] maarten at vivesta dot com
I have the same problem:

PHP 5.2.9RC2-dev (cli) (built: Feb 12 2009 15:10:25)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

On FreeBSD 6.3. Built PHP without FreeBSD patches, just downloaded 
latest and did "cd php5.2-200902121330", "./configure", "make" and 
"./sapi/cli/php"

<?php
while (1)
{
  $a=strtotime ( 'now', time() );
}

Top shows the memory usage growing steadily.
 [2009-02-15 12:54 UTC] derick@php.net
Please send me account details (by email), as I still can't reproduce this.
 [2009-02-17 14:47 UTC] maarten at vivesta dot com
Ok, I've sent you login details to a testmachine by e-mail.
 [2009-02-17 15:45 UTC] danger at FreeBSD dot org
I did so yesterday as well...
 [2009-02-18 01:10 UTC] alex dot franks at soletechnology dot com
I'm also experiencing this bug on FreeBSD 7.

FreeBSD version:
FreeBSD 7.0-STABLE #1: Mon Jul 14 16:07:29 PDT 2008   i386

PHP version:
PHP 5.2.8 with Suhosin-Patch 0.9.6.3 (cli) (built: Feb  7 2009 11:09:59)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
 [2009-02-23 08:59 UTC] danger at FreeBSD dot org
Any news on this? I checked the box and it seems like you logged only once for a few seconds almost a week ago....
 [2009-02-27 10:41 UTC] danger at FreeBSD dot org
verified to still leak with:

root@[temp /basejail/usr/ports/lang/php5]# php -v
PHP 5.2.9 (cli) (built: Feb 27 2009 11:36:57)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
 [2009-02-27 11:44 UTC] derick@php.net
I am not forgetting about this, but at the moment just really occupied. Just as a quick question, this is the *stock* PHP without any ports patches, also, if you set the error level to also show e_Strict messages, do you see anything? Also, do you have the date.timezone setting made in PHP.ini?
 [2009-02-27 13:25 UTC] danger at FreeBSD dot org
Hey there,

I have tried to build a stock php-5.2.9 (no FreeBSD patches or anything else) with ./configure && make. 

When I run my test script as this:
root@[temp /var/ports/distfiles/php-5.2.9]# sapi/cli/php /root/test.php

No modified php.ini is being used, no additional extensions are being loaded. I can still verify that it leaks.
 [2009-02-27 13:53 UTC] danger at FreeBSD dot org
I tried to run my script with php -d error_reporting=E_STRICT test.php and been receiving this error until I stopped the script:

Strict Standards: strtotime(): It is not safe to rely on the system's timezone settings. Please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Berlin' for 'CET/1.0/no DST' instead in /root/test.php on line 10
 [2009-02-27 14:48 UTC] maarten at vivesta dot com
Same here. I've added a date_default_timezone_set() before using 
strtotime() and it removed the error but not the leak.
 [2009-03-09 18:46 UTC] martin at 925 dot dk
This patch (which reverts the fix for bug 45529) against parse_date.c 
seems to fix the leak:

Hence this patch against parse_date.c:
--- parse_date_.c	2009-03-09 19:33:37.000000000 +0100
+++ parse_date.c	2009-03-09 19:33:45.000000000 +0100
@@ -733,7 +733,7 @@
 		}
 #endif
 		/* If we have a TimeZone identifier to start with, use 
it */
-		if (strstr(tz_abbr, "/") || strcmp(tz_abbr, "UTC") == 
0) {
+		if (strstr(tz_abbr, "/")) {
 			if ((res = timelib_parse_tzfile(tz_abbr, 
tzdb)) != NULL) {
 				t->tz_info = res;
 				t->zone_type = TIMELIB_ZONETYPE_ID;
 [2009-03-09 21:41 UTC] martin at 925 dot dk
Removing UTC from the timestamp in php_date.c also fixes the leak:

--- php_date_.c	2009-03-09 22:30:15.000000000 +0100
+++ php_date.c	2009-03-09 22:30:21.000000000 +0100
@@ -1117,7 +1117,7 @@
 		now = timelib_time_ctor();
 
 		initial_ts = emalloc(25);
-		snprintf(initial_ts, 24, "@%ld UTC", preset_ts);
+		snprintf(initial_ts, 24, "@%ld", preset_ts);
 		t = timelib_strtotime(initial_ts, strlen(initial_ts), 
NULL, DATE_TIMEZONEDB); /* we ignore the error here, as this should 
never fail */
 		timelib_update_ts(t, tzi);
 		now->tz_info = tzi;
 [2009-03-11 15:36 UTC] bloudon at townnews dot com
Leak also observed in 5.2.8 and 5.2.9 on Linux.

This patch (against 5.2.9) is working out for us so far in our dev environment:

--- ext/date/php_date.orig.c    2009-03-11 10:07:36.000000000 -0500
+++ ext/date/php_date.c 2009-03-11 10:12:40.000000000 -0500
@@ -1108,7 +1108,7 @@
    long  preset_ts, ts;

    timelib_time *t, *now;
-   timelib_tzinfo *tzi;
+   timelib_tzinfo *tzi, *old_tzi;

    tzi = get_timezone_info(TSRMLS_C);

@@ -1119,10 +1119,14 @@
        initial_ts = emalloc(25);
        snprintf(initial_ts, 24, "@%ld UTC", preset_ts);
        t = timelib_strtotime(initial_ts, strlen(initial_ts), NULL, DATE_TIMEZONEDB); /* we ignore the error here, as this should never fail */
+       old_tzi = t->tz_info;
        timelib_update_ts(t, tzi);
        now->tz_info = tzi;
        now->zone_type = TIMELIB_ZONETYPE_ID;
        timelib_unixtime2local(now, t->sse);
+       if ( old_tzi ) {
+           timelib_tzinfo_dtor(old_tzi);
+       }
        timelib_time_dtor(t);
        efree(initial_ts);
    } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &times, &time_len, &preset_ts) != FAILURE) {
@@ -1141,6 +1145,7 @@
    }

    t = timelib_strtotime(times, time_len, &error, DATE_TIMEZONEDB);
+   old_tzi = t->tz_info;
    error1 = error->error_count;
    timelib_error_container_dtor(error);
    timelib_fill_holes(t, now, TIMELIB_NO_CLONE);
@@ -1148,6 +1153,9 @@
    ts = timelib_date_to_int(t, &error2);

    timelib_time_dtor(now);
+   if ( old_tzi ) {
+       timelib_tzinfo_dtor(old_tzi);
+   }
    timelib_time_dtor(t);

    if (error1 || error2) {
 [2009-03-30 12:25 UTC] kimc at operamail dot com
The last patch fixes the memory leak for me.
 [2009-04-06 10:01 UTC] davide dot ferrari at atrapalo dot com
Sorry for being dumb but does this leak affect memory_limit ? I mean, I can reproduce the memleak with Linux and PHP 5.2.9 but memory_get_usage() output seems constant, although memory occupied by the process itself is getting biger every second, so there's clearly a memleak.
I ask this because I don't know if there is an actual relationship between this bug and some strange cronjob deaths I'm experiencing with PHP 5.2.9.

TIA
 [2009-04-15 07:55 UTC] kimc at operamail dot com
You dont see the memory leak with PHP's memory_get_usage(), and the process wont get killed by PHP's general memory_limit.

PHP doesnt see the memory use, but the kernel does and after some time the kernel will kill it due to ulimit or out of memory.
 [2009-07-07 10:47 UTC] oliver at realtsp dot com
I can confirm that we can reproduce this bug on FreeBSD 7.2 with php5.2.10 and that the patch provided by bloudon at townnews dot com does stop the leak.

I had to manually apply the patch because copying out of the html rarely works, so I have prepared a "clean" version which applies without errors to the current FreeBSD 7.2 port of php5. Here it is:

http://www.realtsp.com/public/patch-ext_date_php_date.c

Oliver
 [2009-07-23 20:26 UTC] scott at crisscott dot com
Reproduced on RHEL 4 (PHP built from source not RPM)
PHP 5.2.9 (cli) (built: May  1 2009 13:47:24) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
    with Zend Debugger v5.2.14, Copyright (c) 1999-2008, by Zend Technologies

Applying the patch from oliver at realtsp dot com slowed down the leak, but did not stop it entirely.
 [2009-08-26 16:42 UTC] heron at xnapid dot com
I can confirm the same leak, running in Apache on Windows.  Apache kills the script after a time limit, but the leaked memory remains leaked; refreshing the same URL causes the total leaked memory to increase from there.  It looks like it leaks 800KB per second or so, and the script is killed after leaking about 30MB.

I'm running PHP 5.2.9-2, which came straight from the default Windows installer.
 [2009-09-02 11:52 UTC] jani@php.net
Reproduced on 32/64 bit servers using latest PHP_5_2 checkout. Does NOT happen with PHP_5_3.
 [2009-09-10 01:15 UTC] sadrak at sogetthis dot com
Problem verified on:
Linux version 2.6.30-1-amd64 (Debian 2.6.30-6) (waldi@debian.org) (gcc version 4.3.4 (Debian 4.3.4-1) ) #1 SMP Sat Aug 15 21:08:31 UTC 2009

Using:
PHP 5.2.10-2 with Suhosin-Patch 0.9.7 (cli) (built: Jul 10 2009 00:34:06)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
    with Suhosin v0.9.28, Copyright (c) 2007, by SektionEins GmbH
 [2010-03-11 15:25 UTC] maarten at vivesta dot com
I've built PHP 5.2 from SVN (r.296066) from scratch on vanilla Debian Lenny and 
ran valgrind on this problem. Here is the output: 

$ valgrind --leak-check=full ./sapi/cli/php -n -r 'strtotime("now",time());'
==21329== Memcheck, a memory error detector.
==21329== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==21329== Using LibVEX rev 1854, a library for dynamic binary translation.
==21329== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==21329== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation 
framework.
==21329== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==21329== For more details, rerun with: -v
==21329==
==21329==
==21329== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 27 from 1)
==21329== malloc/free: in use at exit: 76 bytes in 4 blocks.
==21329== malloc/free: 7,796 allocs, 7,792 frees, 1,305,337 bytes allocated.
==21329== For counts of detected errors, rerun with: -v
==21329== searching for pointers to 4 not-freed blocks.
==21329== checked 429,556 bytes.
==21329==
==21329== 76 (48 direct, 28 indirect) bytes in 1 blocks are definitely lost in 
loss record 4 of 4
==21329==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==21329==    by 0x809DDAA: timelib_tzinfo_ctor (timelib.c:75)
==21329==    by 0x809D0F7: timelib_parse_tzfile (parse_tz.c:277)
==21329==    by 0x8084211: timelib_get_zone (parse_date.re:737)
==21329==    by 0x8085859: timelib_strtotime (parse_date.re:1007)
==21329==    by 0x8080A4C: zif_strtotime (php_date.c:1143)
==21329==    by 0x8284379: zend_do_fcall_common_helper_SPEC 
(zend_vm_execute.h:200)
==21329==    by 0x82710AF: execute (zend_vm_execute.h:92)
==21329==    by 0x8243A26: zend_eval_string (zend_execute_API.c:1223)
==21329==    by 0x8243B7E: zend_eval_string_ex (zend_execute_API.c:1258)
==21329==    by 0x82BCC29: main (php_cli.c:1204)
==21329==
==21329== LEAK SUMMARY:
==21329==    definitely lost: 48 bytes in 1 blocks.
==21329==    indirectly lost: 28 bytes in 3 blocks.
==21329==      possibly lost: 0 bytes in 0 blocks.
==21329==    still reachable: 0 bytes in 0 blocks.
==21329==         suppressed: 0 bytes in 0 blocks.

Please let me know if there is any more I can do, next to fixing the bug 
obviously... :-) I'm looking in to that...
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sat Apr 19 14:01:50 2014 UTC