PHP 4.0 Bug #3640: memory overwrite in expand_filepath when using include("../somefile.inc")

From: Date: Sun, 27 Feb 2000 04:09:27 +0000
Subject: PHP 4.0 Bug #3640: memory overwrite in expand_filepath when using include("../somefile.inc")
Groups: php.dev 
Request: Send a blank email to php-dev+get-16067@lists.php.net to get a copy of this message
From: gwh@acm.org Operating system: Windows NT 4.0 Server SP 5 PHP version: 4.0 Beta 4 Patch Level 1 PHP Bug Type: Reproduceable crash Bug description: memory overwrite in expand_filepath when using include("../somefile.inc") modules utilized in this test: (commented out all extensions, recompiled debug non thread safe under VC++5) php.exe phpnts.dll Friends, It took me a while to figure this out, since I have run the same code on all versions from php3 through the php4 betas and onto php4pl1, without this type of failure. Here is the problem. I may be the only one that uses an include statement of a file in a parent directory, but it's failing now. . I've distilled it down to two simple scripts. lets say your sites sit under the path: d:\websites\website1 place the script "empty.inc" in the directory d:\websites, containing <?php print("empty"); ?> place another script "testempty.php" in the directory d:\websites\websites1, containing <?php include("../empty.inc"); print("testempty"); ?> my document root is d:\websites\websites1 and when I reference http:\\website1\testempty.php I get a debug assertion ( rebuilt the modules in debug mode, non threadsafe, compiled in VC5.0 ) in dbgheap.c, line 1017, in the function free_dbg_lk. Here is the backtrace: dbgheap.c, 1017: _free_dbg_lk(void *,int) dbgheap.c, 970: _free_dbg(void *,int) dbgheap.c, 926: free(void *) fopen-wrappers.c, 989: expand_filepath(char *) fopen-wrappers.c, 336: php_open_with_path(char *,char *,char *,char *) ... The problem occurs in expand_filepath() .... It is passed the pathname of "../empty.inc". The parent directory file reference causes this code to execute in line 976: if(filepath[1] == '.') { /*erase the last directory name from the path */ while(*cwd_end != '/') { *cwd_end--=0; } filepath++; } if(cwd_end > cwd && (*cwd_end == '/') { *cwd_end-- = 0; } The problem happens because on windows getcwd() returns "d:\websites\website1". Notice the back slashes. I don't know why this hasn't failed before. The loop while(*cwd_end!='/') *cwd_end--=0 happily zeros the string going back, back, ba,ba,ba,ba,ba,ba baaaak (chris berman, ESPN) until it finds a forward slash. When it gets down to the statement "free(cwd)" in line 989, all of the malloc information is destroyed and it asserts, and would cause an exception if it goes any further. I modified the code to add another check for the alternate case : if(filepath[1] == '.') { /*erase the last directory name from the path */ while(*cwd_end != '/' && *cwd_end != '\\') { *cwd_end--=0; } filepath++; } if(cwd_end > cwd && (*cwd_end == '/' || *cwd_end=='\\') { *cwd_end-- = 0; } This compiled and worked wonderfully. I scanned the rest of the code for getcwd() andI didn't see another direct exposures due to the slashes on windows. Regards, Garfield

« previous php.dev (#16067) next »