]> granicus.if.org Git - php/commitdiff
Fixed bug #39367 (clearstatcache() doesn't clear realpath cache)
authorDmitry Stogov <dmitry@php.net>
Mon, 22 Jan 2007 09:31:46 +0000 (09:31 +0000)
committerDmitry Stogov <dmitry@php.net>
Mon, 22 Jan 2007 09:31:46 +0000 (09:31 +0000)
Fixed bug #40092 (chroot() doesn't clear realpath cache)

NEWS
TSRM/tsrm_virtual_cwd.c
TSRM/tsrm_virtual_cwd.h
ext/standard/dir.c
ext/standard/filestat.c
ext/standard/tests/file/bug39367.phpt [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 57c33e9779aa7abca631fd4bd9183d2729fe3cd1..8295fb0aa0a8faeb8a00c86b546be5a559e20853 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,7 +5,10 @@ PHP                                                                        NEWS
   (Tony)
 - Fixed bug #40169 (CURLOPT_TCP_NODELAY only available in curl >= 7.11.2). 
   (Tony)
+- Fixed bug #40092 (chroot() doesn't clear realpath cache). (Dmitry)
 - Fixed bug #39450 (getenv() fills other super-globals). (Ilia, Tony)
+- Fixed bug #39367 (clearstatcache() doesn't clear realpath cache).
+  (j at pureftpd dot org, Dmitry)
 
 18 Jan 2007, PHP 5.2.1RC3
 - Added read-timeout context option "timeout" for HTTP streams. (Hannes,
index 959cc7d76e7e371fed19d55a13587e3895e23e44..36bce0b5e969ee93fbe2859723327d66ef8d8355 100644 (file)
@@ -249,18 +249,7 @@ static void cwd_globals_ctor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
 static void cwd_globals_dtor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
 {
        CWD_STATE_FREE(&cwd_globals->cwd);
-       {
-               int i;
-
-               for (i = 0; i < sizeof(cwd_globals->realpath_cache)/sizeof(cwd_globals->realpath_cache[0]); i++) {
-                       realpath_cache_bucket *p = cwd_globals->realpath_cache[i];
-                       while (p != NULL) {
-                               realpath_cache_bucket *r = p;
-                               p = p->next;
-                               free(r);
-                       }
-               }
-       }
+       realpath_cache_clean(TSRMLS_C);
 }
 
 static char *tsrm_strndup(const char *s, size_t length)
@@ -394,6 +383,42 @@ static inline unsigned long realpath_cache_key(const char *path, int path_len)
        return h;
 }
 
+CWD_API void realpath_cache_clean(TSRMLS_D)
+{
+       int i;
+
+       for (i = 0; i < sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]); i++) {
+               realpath_cache_bucket *p = CWDG(realpath_cache)[i];
+               while (p != NULL) {
+                       realpath_cache_bucket *r = p;
+                       p = p->next;
+                       free(r);
+               }
+               CWDG(realpath_cache)[i] = NULL;
+       }
+       CWDG(realpath_cache_size) = 0;
+}
+
+CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC)
+{
+       unsigned long key = realpath_cache_key(path, path_len);
+       unsigned long n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
+       realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
+
+       while (*bucket != NULL) {
+               if (key == (*bucket)->key && path_len == (*bucket)->path_len &&
+                          memcmp(path, (*bucket)->path, path_len) == 0) {
+                       realpath_cache_bucket *r = *bucket;
+                       *bucket = (*bucket)->next;
+                       CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1;
+                       free(r);
+                       return;
+               } else {
+                       bucket = &(*bucket)->next;
+               }
+       }
+}
+
 static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, int realpath_len, time_t t TSRMLS_DC)
 {
        long size = sizeof(realpath_cache_bucket) + path_len + 1 + realpath_len + 1;
index b029823fd9ad6deea46ae92e19b47ea214602594..437cc4534873659cd2120c31cef5354fe6e78a35 100644 (file)
@@ -226,6 +226,9 @@ extern virtual_cwd_globals cwd_globals;
 # define CWDG(v) (cwd_globals.v)
 #endif
 
+CWD_API void realpath_cache_clean(TSRMLS_D);
+CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC);
+
 /* The actual macros to be used in programs using TSRM
  * If the program defines VIRTUAL_DIR it will use the
  * virtual_* functions 
index 376c0e4590d1a898180548f54bbbf33aacca671f..fd8b4140cb0fc8306b8f7b932215717ff6fef9df 100644 (file)
@@ -257,12 +257,13 @@ PHP_FUNCTION(chroot)
        }
        
        ret = chroot(str);
-       
        if (ret != 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (errno %d)", strerror(errno), errno);
                RETURN_FALSE;
        }
 
+       realpath_cache_clean(TSRMLS_C);
+       
        ret = chdir("/");
        
        if (ret != 0) {
index b68dec9366c0546ffdc6da2d4e08db7c41f3a8cf..4411924d494d3cca75e02812c9c9212058701c51 100644 (file)
@@ -673,6 +673,7 @@ PHP_FUNCTION(clearstatcache)
                efree(BG(CurrentLStatFile));
                BG(CurrentLStatFile) = NULL;
        }
+       realpath_cache_clean(TSRMLS_C);
 }
 /* }}} */
 
diff --git a/ext/standard/tests/file/bug39367.phpt b/ext/standard/tests/file/bug39367.phpt
new file mode 100755 (executable)
index 0000000..667e33d
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Bug #39367 (clearstatcache() doesn't clear realpath cache)
+--FILE--
+<?php
+function test() {
+  unlink('/tmp/1link');
+  unlink('/tmp/1tmp');
+  unlink('/tmp/testfile1');
+
+  file_put_contents('/tmp/testfile1', 'ok');
+  symlink('/tmp/testfile1', '/tmp/1tmp');
+  rename('/tmp/1tmp', '/tmp/1link');
+  echo file_get_contents('/tmp/1link')."\n";
+
+  unlink('/tmp/1link');
+  clearstatcache();
+
+  echo file_get_contents('/tmp/1link')."\n";
+
+  unlink('/tmp/1link');
+  unlink('/tmp/1tmp');
+  unlink('/tmp/testfile1');
+}
+@test();
+?>
+--EXPECT--
+ok