From:             [EMAIL PROTECTED]
Operating system: Linux
PHP version:      4.2.0
PHP Bug Type:     Scripting Engine problem
Bug description:  Mkdir fails under safe mode

Unable to create directory by mkdir PHP function when PHP runs under safe
mode.
The following command fails:
if (!mkdir("$PHP_DOCUMENT_ROOT/$path", 0770))when $path has a trailing
slash.

There is two possible solutions.
Both shown below and can also be found at
http://www.cf1.ru/~byg/patch/php/safe_mode.c.patch
http://www.cf1.ru/~byg/patch/php/mkdir_get_rid_trailing_slashes.patch
or
ftp://ftp.cf1.ru/pub/patches/php/

1) change php_checkuid in main/safe_mode.c 
2) change mkdir handler in ext/standard/file.c

1st patch:
=================================================
--- main/safe_mode.c.orig       Thu Apr  4 13:58:00 2002
+++ main/safe_mode.c    Tue Apr 16 12:29:53 2002
@@ -49,7 +49,7 @@
        int ret, nofile=0;
        long uid=0L, gid=0L, duid=0L, dgid=0L;
        char path[MAXPATHLEN];
-       char *s;
+       char *s, *anchor;
        TSRMLS_FETCH();

        if (!filename) {
@@ -105,19 +105,42 @@
                                *s = '\0';
                }
        } else { /* CHECKUID_ALLOW_ONLY_DIR */
-               s = strrchr(filename, DEFAULT_SLASH);
-
-               if (s == filename) {
-                       /* root dir */
-                       path[0] = DEFAULT_SLASH;
-                       path[1] = '\0';
-               } else if (s) {
-                       *s = '\0';
+               /* look for a trail slash --byg */
+               s = (char *) strrchr(filename, DEFAULT_SLASH);
+               /* if s points s is either equal to or less than filename,
NULL as last resort (never s>filename) */
+               if ((filename + strlen(filename) - 1) > s)
+               {
+                   if (s)
+                   { /* path like /a/b or a/b, skip tail */
+                       *s='\0';
                        VCWD_REALPATH(filename, path);
                        *s = DEFAULT_SLASH;
-               } else {
+                   }
+                   else
+                   { /* trivial path like aaa */
                        VCWD_GETCWD(path, MAXPATHLEN);
-               }
+                   }
+               }
+               else
+               {
+                   /* get rid contiguous trailing slashes if any */
+                   while( s>filename && *(s-1) == DEFAULT_SLASH)
+                       --s;
+                   if (s > filename)
+                   { /* mark current position then look for the next
slash group */
+                       anchor = s; *s = '\0'; s = (char*)
strrchr(filename, '/');
+                       if (s) *s = '\0'; /* path was either /a/b/// */
+                       VCWD_REALPATH(filename, path); /* or just a/// */
+                       *anchor = DEFAULT_SLASH; /* restore slashes */
+                       if (s) *s = DEFAULT_SLASH;
+                   }
+                   /* rare case - root dir */
+                   else
+                   {
+                       path[0] = DEFAULT_SLASH;
+                       path[1] = '\0';
+                   }
+               }
        } /* end CHECKUID_ALLOW_ONLY_DIR */
       if (mode != CHECKUID_ALLOW_ONLY_FILE) {
==================================================
2nd patch:
==================================================
 --- ext/standard/file.c.orig    Tue Apr 16 22:34:55 2002
+++ ext/standard/file.c Tue Apr 16 23:19:29 2002
@@ -1454,10 +1454,21 @@
 {
        int dir_len, ret;
        mode_t mode = 0777;
-       char *dir;
+       char *dir, *s;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &dir,
&dir_len, &mode) == FAILURE) {
                return;
+       }
+
+       /* get rid trailing slashes if any --byg */
+       if (dir) {
+           s = dir + strlen(dir) - 1;
+           if (*s == DEFAULT_SLASH) {
+               while((*(s-1) == DEFAULT_SLASH) && (s > dir))
+                   --s;
+               if (s > dir)
+                   *(s) = '\0';
+           }
        }
 
        if (PG(safe_mode) &&(!php_checkuid(dir, NULL,
CHECKUID_ALLOW_ONLY_DIR))) {

        if (mode != CHECKUID_ALLOW_ONLY_FILE) {
=====================================================

-- 
Edit bug report at http://bugs.php.net/?id=16638&edit=1
-- 
Fixed in CVS:        http://bugs.php.net/fix.php?id=16638&r=fixedcvs
Fixed in release:    http://bugs.php.net/fix.php?id=16638&r=alreadyfixed
Need backtrace:      http://bugs.php.net/fix.php?id=16638&r=needtrace
Try newer version:   http://bugs.php.net/fix.php?id=16638&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=16638&r=support
Expected behavior:   http://bugs.php.net/fix.php?id=16638&r=notwrong
Not enough info:     http://bugs.php.net/fix.php?id=16638&r=notenoughinfo
Submitted twice:     http://bugs.php.net/fix.php?id=16638&r=submittedtwice

Reply via email to