php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39105 Possible memory leak when require()-ing new files in estrndup
Submitted: 2006-10-10 10:15 UTC Modified: 2006-12-15 01:00 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: ivoras at yahoo dot com Assigned:
Status: No Feedback Package: Filesystem function related
PHP Version: 5.2 OS: FreeBSD
Private report: No CVE-ID: None
 [2006-10-10 10:15 UTC] ivoras at yahoo dot com
Description:
------------
PHP compiled with debugging reports memory leaks. It technically really IS a memory leak in the script code, but should that influence the scripting engine?

Reproduce code:
---------------
<?php
$f = fopen('aaa', 'w+');
fwrite($f, "bcde\n");
?>


Expected result:
----------------
A working program

Actual result:
--------------
[Tue Oct 10 12:10:55 2006]  Script:  'bla.php'
/usr/ports/lang/php5/work/php-5.1.6/main/main.c(1708) :  Freeing 0x085ACCA4 (26 bytes), script=bla.php
=== Total 1 memory leaks detected ===


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-10-10 10:45 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip


 [2006-10-18 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2006-12-06 14:35 UTC] ivoras at yahoo dot com
Tried 6.2-release with same results. It looks like it happens when including files with require_once.

Error message:

> php b.php 
[Wed Dec  6 15:18:51 2006]  Script:  'b.php'
/usr/ports/lang/php5/work/php-5.2.0/main/main.c(1729) :  Freeing 0x0861FAFC (40 bytes), script=b.php
[Wed Dec  6 15:18:51 2006]  Script:  'b.php'
/usr/ports/lang/php5/work/php-5.2.0/main/fopen_wrappers.c(543) :  Freeing 0x0861FB48 (40 bytes), script=b.php

The example script, "b.php" is:

<?php
require_once('a.php');

class B extends A {
    function __construct($par) {
        echo "Hello from B constructor\n";
    }
}
?>

a.php is:

<?php
class A {
    function __construct($param) {
        echo "A::constructor";
    }
}
?>

The code for main.c (part of PHP interpreter) is:

1717         /* Only lookup the real file path and add it to the included_files list if already opened
1718          *   otherwise it will get opened and added to the included_files list in zend_execute_scripts
1719          */
1720         if (primary_file->filename &&
1721             primary_file->opened_path == NULL &&
1722             primary_file->type != ZEND_HANDLE_FILENAME) {
1723             int realfile_len;
1724             int dummy = 1;
1725 
1726             if (expand_filepath(primary_file->filename, realfile TSRMLS_CC)) {
1727                 realfile_len =  strlen(realfile);
1728                 zend_hash_add(&EG(included_files), realfile, realfile_len+1, (void *)&dummy, sizeof(int), NULL);
1729                 primary_file->opened_path = estrndup(realfile, realfile_len);
1730             }
1731         }


The code for fopen_wrappers is:
513 /* {{{ expand_filepath
514  */
515 PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC)
516 {
517     cwd_state new_state;
518     char cwd[MAXPATHLEN];
519     char *result;
520 
521     if (IS_ABSOLUTE_PATH(filepath, strlen(filepath))) {
522         cwd[0] = '\0';
523     } else{
524         result = VCWD_GETCWD(cwd, MAXPATHLEN);
525         if (!result) {
526             cwd[0] = '\0';
527         }
528     }
529 
530     new_state.cwd = strdup(cwd);
531     new_state.cwd_length = strlen(cwd);
532 
533     if(virtual_file_ex(&new_state, filepath, NULL, 1)) {
534         free(new_state.cwd);
535         return NULL;
536     }
537 
538     if(real_path) {
539         int copy_len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length;
540         memcpy(real_path, new_state.cwd, copy_len);
541         real_path[copy_len]='\0';
542     } else {
543         real_path = estrndup(new_state.cwd, new_state.cwd_length);
544     }
545     free(new_state.cwd);
546 
547     return real_path;
548 }
549 /* }}} */
 [2006-12-06 14:59 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip

Cannot reproduce anything like that both on Freebsd & Linux.
 [2006-12-06 17:23 UTC] ivoras at yahoo dot com
The recent feedback got me thinking - I use a template extensions.ini (list of extensions) on all my systems and when I remove it the leak is gone. Thus, I managed to reproduce the leek because the loaded extensions are the same on every system.

There's a known php-crashing bug with PHP (at least versions 5.1 and 5.2) on FreeBSD that's got something to do with the order extensions are loaded, so this might be an aspect of it. My list is:

extension=bz2.so
extension=session.so
extension=mhash.so
extension=zlib.so
extension=mbstring.so
extension=sockets.so
extension=mcrypt.so
extension=pcre.so
extension=simplexml.so
extension=xml.so
extension=apc.so
extension=sqlite.so
extension=memcache.so
extension=dom.so
extension=iconv.so
extension=mysql.so
extension=gd.so
extension=pgsql.so
extension=ldap.so
extension=tokenizer.so

I'll try fiddling with the order of extensions and report results.
 [2006-12-15 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC