]> 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:32:55 +0000 (09:32 +0000)
committerDmitry Stogov <dmitry@php.net>
Mon, 22 Jan 2007 09:32:55 +0000 (09:32 +0000)
Fixed bug #40092 (chroot() doesn't clear realpath cache)

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]

index e590680e67719e4d6b92770fb32430a485336ee0..0c7dc6d3f40b36de0d82fa741350d29f8520a346 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)
@@ -393,6 +382,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 c2249b5c9ba2ef8e95a4c19141eb2dadc5a1a83c..27e392e7e1b75dae2731cc410688597bb5ee2120 100644 (file)
@@ -243,6 +243,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 24fc2d0f4e9194f1dba15abafd3dd870aaf354c3..e489072e2c3e418ceedce16f2b6f3dd312fbbb3b 100644 (file)
@@ -286,6 +286,8 @@ PHP_FUNCTION(chroot)
                RETURN_FALSE;
        }
 
+       realpath_cache_clean(TSRMLS_C);
+       
        ret = chdir("/");
        
        if (ret != 0) {
index 21bb42a6d16a96098e924e24a36cf0c5c9d0d6cf..68190ad27fde23f2c5945ab307224b9cc42a4a75 100644 (file)
@@ -744,6 +744,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