From 7d1110a3fbcc562ff51a0cc5864180b381ac1a0e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 22 Jan 2007 09:32:55 +0000 Subject: [PATCH] Fixed bug #39367 (clearstatcache() doesn't clear realpath cache) Fixed bug #40092 (chroot() doesn't clear realpath cache) --- TSRM/tsrm_virtual_cwd.c | 49 ++++++++++++++++++++------- TSRM/tsrm_virtual_cwd.h | 3 ++ ext/standard/dir.c | 2 ++ ext/standard/filestat.c | 1 + ext/standard/tests/file/bug39367.phpt | 27 +++++++++++++++ 5 files changed, 70 insertions(+), 12 deletions(-) create mode 100755 ext/standard/tests/file/bug39367.phpt diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c index e590680e67..0c7dc6d3f4 100644 --- a/TSRM/tsrm_virtual_cwd.c +++ b/TSRM/tsrm_virtual_cwd.c @@ -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; diff --git a/TSRM/tsrm_virtual_cwd.h b/TSRM/tsrm_virtual_cwd.h index c2249b5c9b..27e392e7e1 100644 --- a/TSRM/tsrm_virtual_cwd.h +++ b/TSRM/tsrm_virtual_cwd.h @@ -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 diff --git a/ext/standard/dir.c b/ext/standard/dir.c index 24fc2d0f4e..e489072e2c 100644 --- a/ext/standard/dir.c +++ b/ext/standard/dir.c @@ -286,6 +286,8 @@ PHP_FUNCTION(chroot) RETURN_FALSE; } + realpath_cache_clean(TSRMLS_C); + ret = chdir("/"); if (ret != 0) { diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index 21bb42a6d1..68190ad27f 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -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 index 0000000000..667e33dca1 --- /dev/null +++ b/ext/standard/tests/file/bug39367.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #39367 (clearstatcache() doesn't clear realpath cache) +--FILE-- + +--EXPECT-- +ok -- 2.40.0