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

Reply via email to