ID: 3697 Updated by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] -Status: Analyzed +Status: Closed Bug Type: Feature/Change Request Operating System: BSD/OS 4.0.1 PHP Version: 4.0 Beta 4 Patch Level 1 New Comment:
seems to be fixed. Previous Comments: ------------------------------------------------------------------------ [2000-08-01 01:01:08] [EMAIL PROTECTED] DJM reports that problem is fixed. However, he suggests that there is a better solution to the problem than was implemented. See message below. "I just checked the CVS version. The primary bug I reported is fixed in the current sources, though in a somewhat less robust (but simpler) way than I suggested. I would still like to have more warning messages instead of silent failures in various exceptional conditions, as suggested in my patch; that has not been done so far. Also, spurious whitespace has been added in a comment in main/php_realpath.c:260: /* C heck for overflow */ " ------------------------------------------------------------------------ [2000-07-29 23:59:54] [EMAIL PROTECTED] Have you tried a recent release? If so, does the problem still occur? ------------------------------------------------------------------------ [2000-03-02 01:24:46] [EMAIL PROTECTED] Some more warning messages to alert about exceptional conditions would be helpful. Also, there's a misformatted warning message due to the appending of " in <script>...". And, there's a place in the distributed code that's missing the PHP_WIN32 case. So here's my final (I think) suggested patch: Index: fopen-wrappers.c =================================================================== retrieving revision 1.2 diff -u -r1.2 fopen-wrappers.c --- fopen-wrappers.c 2000/03/01 04:32:29 1.2 +++ fopen-wrappers.c 2000/03/02 06:14:53 @@ -120,21 +120,26 @@ } /* Resolve the real path into resolved_name */ - if ((php_realpath(path, resolved_name) != NULL) && (php_realpath(local_open_basedir, resolved_basedir) != NULL)) { + if (php_realpath(path, resolved_name) == NULL) { + /* Unable to resolve the real path, return -1 */ + return -1; + } else if (php_realpath(local_open_basedir, resolved_basedir) == NULL) { + /* Unable to resolve the real path, return -1 */ + php_error(E_WARNING, "cannot resolve open_basedir %s", local_open_basedir); + return -1; + } else { /* Check the path */ #ifdef PHP_WIN32 - if (strncasecmp(resolved_basedir, resolved_name, strlen(resolved_basedir)) == 0) { + if (strncasecmp(resolved_basedir, resolved_name, strlen(resolved_basedir)) == 0) #else - if (strncmp(resolved_basedir, resolved_name, strlen(resolved_basedir)) == 0) { + if (strncmp(resolved_basedir, resolved_name, strlen(resolved_basedir)) == 0) #endif + { /* File is in the right directory */ return 0; } else { return -1; } - } else { - /* Unable to resolve the real path, return -1 */ - return -1; } } @@ -170,7 +175,7 @@ ptr = end; } - php_error(E_WARNING, "open_basedir restriction in effect. File is in wrong directory."); + php_error(E_WARNING, "open_basedir restriction in effect. File is in wrong directory"); efree(pathbuf); return -1; } Index: php_realpath.c =================================================================== retrieving revision 1.1.1.1 diff -u -r1.1.1.1 php_realpath.c --- php_realpath.c 2000/03/01 04:23:33 1.1.1.1 +++ php_realpath.c 2000/03/02 06:20:56 @@ -97,6 +97,7 @@ if (getcwd(path_construction, MAXPATHLEN-1) == NULL) { /* Unable to get cwd */ resolved_path[0] = 0; + php_error(E_WARNING, "cannot get current directory"); return NULL; } strcat(path_construction, "/"); @@ -213,7 +214,10 @@ /* Check the current location to see if it is a symlink */ if((linklength = readlink(path_construction, buf, MAXPATHLEN)) != -1) { /* Check linkcount */ - if (linkcount > MAXSYMLINKS) return NULL; + if (linkcount > MAXSYMLINKS) { + php_error(E_WARNING, "detected symlink loop in %s", path); + return NULL; + } /* Count this symlink */ linkcount++; @@ -222,7 +226,10 @@ buf[linklength] = 0; /* Check for overflow */ - if ((strlen(workpos) + strlen(buf) + 1) >= MAXPATHLEN) return NULL; + if ((strlen(workpos) + strlen(buf) + 1) >= MAXPATHLEN) { + php_error(E_WARNING, "overflow in %s", path); + return NULL; + } /* Remove the symlink-component wrom path_construction */ writepos--; /* move to '/' */ @@ -251,12 +258,31 @@ } /* Check if the resolved path is a directory */ - if (stat(path_construction, &filestat) != 0) return NULL; + if (stat(path_construction, &filestat) != 0) { + /* It doesn't exist yet; check the directory it's in instead. */ +#ifdef PHP_WIN32 + while (*--writepos != '\\' && writepos > path_construction) +#else + while (*--writepos != '/' && writepos > path_construction) +#endif + ; + *writepos = 0; + if (stat(path_construction, &filestat) != 0) { + return NULL; + } + } if (S_ISDIR(filestat.st_mode)) { /* It's a directory, append a / if needed */ +#ifdef PHP_WIN32 + if (*(writepos-1) != '\\') { +#else if (*(writepos-1) != '/') { +#endif /* Check for overflow */ - if ((strlen(workpos) + 2) >= MAXPATHLEN) return NULL; + if ((strlen(workpos) + 2) >= MAXPATHLEN) { + php_error(E_WARNING, "overflow in %s", path); + return NULL; + } *writepos++ = '/'; *writepos = 0; ------------------------------------------------------------------------ [2000-03-02 01:05:37] [EMAIL PROTECTED] I should mention that an appropriate #ifdef PHP_WIN32 case would also have to be added. Actually, the win32 support could be more cleanly implemented by doing #ifdef PHP_WIN32 #define DIRSEP '\\' #else #define DIRSEP '/' #endif instead of duplicating a lot of while loops and ifs. ------------------------------------------------------------------------ [2000-03-02 00:57:16] [EMAIL PROTECTED] I have open_basedir set and I am trying to create a file under that directory using $fp = fopen("cities.wddx", "w"); However, it fails: <b>Warning</b>: open_basedir restriction in effect. File is in wrong directory in <b>/homes/web/testtest5/html/serialize.php</b> on line <b>17</b><br> Adding some more warning messages to the PHP source code reveals that the stat() toward the end of php_realpath() is the culprit. Of course it can't stat the file if I'm trying to create it. A suggested fix: Index: php_realpath.c @@ -251,12 +258,25 @@ } /* Check if the resolved path is a directory */ - if (stat(path_construction, &filestat) != 0) return NULL; + if (stat(path_construction, &filestat) != 0) { + /* It doesn't exist yet; check the directory it's in instead. */ + while (*--writepos != '/' && writepos > path_construction) + ; + *writepos = 0; + if (stat(path_construction, &filestat) != 0) { + return NULL; + } + } if (S_ISDIR(filestat.st_mode)) { /* It's a directory, append a / if needed */ if (*(writepos-1) != '/') { /* Check for overflow */ ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=3697&edit=1