From: Dmitry Stogov Date: Wed, 20 Sep 2006 07:35:59 +0000 (+0000) Subject: Fixed bug #38579 (include_once() may include the same file twice) X-Git-Tag: php-5.2.0RC5~122 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=811634bd8adab5ae2e26c2d169894b181eef17f3;p=php Fixed bug #38579 (include_once() may include the same file twice) --- diff --git a/NEWS b/NEWS index bcd6362133..052be56a5b 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS (Tony) - Fixed bug #38623 (leaks in a tricky code with switch() and exceptions). (Dmitry) +- Fixed bug #38579 (include_once() may include the same file twice). (Dmitry) - Fixed bug #38574 (missing curl constants and improper constant detection). (Ilia) - Fixed bug #37870 (pgo_pgsql tries to de-allocate unused statements). diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c index 0b333ede04..7afc8dafbd 100644 --- a/TSRM/tsrm_virtual_cwd.c +++ b/TSRM/tsrm_virtual_cwd.c @@ -366,23 +366,11 @@ static inline realpath_cache_bucket* realpath_cache_find(const char *path, int p CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath) { int path_length = strlen(path); - char *ptr, *path_copy; - char *tok = NULL; - int ptr_length; cwd_state old_state; - int ret = 0; - int copy_amount = -1; - char *free_path; - unsigned char is_absolute = 0; -#ifndef TSRM_WIN32 - char resolved_path[MAXPATHLEN]; -#else - char *new_path; -#endif char orig_path[MAXPATHLEN]; - int orig_path_len = 0; realpath_cache_bucket *bucket; time_t t = 0; + int ret; TSRMLS_FETCH(); if (path_length == 0) @@ -390,21 +378,29 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func if (path_length >= MAXPATHLEN) return (1); - if (use_realpath && CWDG(realpath_cache_size_limit)) { - if (IS_ABSOLUTE_PATH(path, path_length) || (state->cwd_length < 1)) { - memcpy(orig_path, path, path_length+1); - orig_path_len = path_length; - } else { - orig_path_len = path_length + state->cwd_length + 1; - if (orig_path_len >= MAXPATHLEN) { - return 1; - } - memcpy(orig_path, state->cwd, state->cwd_length); - orig_path[state->cwd_length] = DEFAULT_SLASH; - memcpy(orig_path + state->cwd_length + 1, path, path_length + 1); +#if VIRTUAL_CWD_DEBUG + fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path); +#endif + + /* cwd_length can be 0 when getcwd() fails. + * This can happen under solaris when a dir does not have read permissions + * but *does* have execute permissions */ + if (!IS_ABSOLUTE_PATH(path, path_length) && (state->cwd_length > 1)) { + int orig_path_len = path_length + state->cwd_length + 1; + + if (orig_path_len >= MAXPATHLEN) { + return 1; } + memcpy(orig_path, state->cwd, state->cwd_length); + orig_path[state->cwd_length] = DEFAULT_SLASH; + memcpy(orig_path + state->cwd_length + 1, path, path_length + 1); + path = orig_path; + path_length = orig_path_len; + } + + if (use_realpath && CWDG(realpath_cache_size_limit)) { t = CWDG(realpath_cache_ttl)?time(NULL):0; - if ((bucket = realpath_cache_find(orig_path, orig_path_len, t TSRMLS_CC)) != NULL) { + if ((bucket = realpath_cache_find(path, path_length, t TSRMLS_CC)) != NULL) { int len = bucket->realpath_len; CWD_STATE_COPY(&old_state, state); @@ -421,107 +417,55 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func } } } + + if (use_realpath) { #if !defined(TSRM_WIN32) && !defined(NETWARE) - /* cwd_length can be 0 when getcwd() fails. - * This can happen under solaris when a dir does not have read permissions - * but *does* have execute permissions */ - if (IS_ABSOLUTE_PATH(path, path_length) || (state->cwd_length < 1)) { - if (use_realpath) { - if (realpath(path, resolved_path)) { /* Note: Not threadsafe on older *BSD's */ - path = resolved_path; - path_length = strlen(path); - } else { - /* disable for now - return 1; */ - } - } - } else { /* Concat current directory with relative path and then run realpath() on it */ - char *tmp; - char *ptr; + char resolved_path[MAXPATHLEN]; - ptr = tmp = (char *) malloc(state->cwd_length+path_length+sizeof("/")); - if (!tmp) { - return 1; - } - memcpy(ptr, state->cwd, state->cwd_length); - ptr += state->cwd_length; - *ptr++ = DEFAULT_SLASH; - memcpy(ptr, path, path_length); - ptr += path_length; - *ptr = '\0'; - if (strlen(tmp) >= MAXPATHLEN) { - free(tmp); - return 1; - } - if (use_realpath) { - if (realpath(tmp, resolved_path)) { - path = resolved_path; - path_length = strlen(path); - } else { - /* disable for now - free(tmp); - return 1; */ - } - } - free(tmp); - } -#endif -#if defined(TSRM_WIN32) - { - int new_path_length; - - new_path_length = GetLongPathName(path, NULL, 0); - if (new_path_length == 0) { - goto php_failed_getlongpath; + if (!realpath(path, resolved_path)) { /* Note: Not threadsafe on older *BSD's */ + goto no_realpath; } + CWD_STATE_COPY(&old_state, state); - /* GetLongPathName already counts the \0 */ - new_path = (char *) malloc(new_path_length); - if (!new_path) { - return 1; - } - - if (GetLongPathName(path, new_path, new_path_length) != 0) { - path = new_path; - path_length = new_path_length; - } else { - free(new_path); -php_failed_getlongpath: - new_path = NULL; - } - } + state->cwd_length = strlen(resolved_path); + state->cwd = (char *) realloc(state->cwd, state->cwd_length+1); + memcpy(state->cwd, resolved_path, state->cwd_length+1); +#else + goto no_realpath; #endif - free_path = path_copy = tsrm_strndup(path, path_length); - - CWD_STATE_COPY(&old_state, state); -#if VIRTUAL_CWD_DEBUG - fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path); + } else { + char *ptr, *path_copy, *free_path; + char *tok = NULL; + int ptr_length; + +no_realpath: + + free_path = path_copy = tsrm_strndup(path, path_length); + CWD_STATE_COPY(&old_state, state); + +#ifdef TSRM_WIN32 + if (path_length >= 2 && path[1] == ':') { + state->cwd = (char *) realloc(state->cwd, 2 + 1); + state->cwd[0] = toupper(path[0]); + state->cwd[1] = ':'; + state->cwd[2] = '\0'; + state->cwd_length = 2; + path_copy += 2; + } else if (IS_UNC_PATH(path, path_length)) { + state->cwd = (char *) realloc(state->cwd, 1 + 1); + state->cwd[0] = DEFAULT_SLASH; + state->cwd[1] = '\0'; + state->cwd_length = 1; + path_copy += 2; + } else { #endif - if (IS_ABSOLUTE_PATH(path_copy, path_length)) { - copy_amount = COPY_WHEN_ABSOLUTE(path_copy); - is_absolute = 1; + state->cwd = (char *) realloc(state->cwd, 1); + state->cwd[0] = '\0'; + state->cwd_length = 0; #ifdef TSRM_WIN32 - } else if (IS_SLASH(path_copy[0])) { - copy_amount = 2; -#endif - } - - if (copy_amount != -1) { - state->cwd = (char *) realloc(state->cwd, copy_amount + 1); - if (copy_amount) { - if (is_absolute) { - memcpy(state->cwd, path_copy, copy_amount); - path_copy += copy_amount; - } else { - memcpy(state->cwd, old_state.cwd, copy_amount); - } } - state->cwd[copy_amount] = '\0'; - state->cwd_length = copy_amount; - } - - - if (state->cwd_length > 0 || IS_ABSOLUTE_PATH(path, path_length)) { +#endif + ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok); while (ptr) { ptr_length = strlen(ptr); @@ -551,7 +495,8 @@ php_failed_getlongpath: state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1+1); #ifdef TSRM_WIN32 /* Windows 9x will consider C:\\Foo as a network path. Avoid it. */ - if ((state->cwd[state->cwd_length-1]!='\\' && state->cwd[state->cwd_length-1]!='/') || + if (state->cwd_length < 2 || + (state->cwd[state->cwd_length-1]!='\\' && state->cwd[state->cwd_length-1]!='/') || IsDBCSLeadByte(state->cwd[state->cwd_length-2])) { state->cwd[state->cwd_length++] = DEFAULT_SLASH; } @@ -575,32 +520,42 @@ php_failed_getlongpath: state->cwd[state->cwd_length++] = DEFAULT_SLASH; #endif memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1); + +#ifdef TSRM_WIN32 + if (use_realpath) { + WIN32_FIND_DATA data; + HANDLE hFind; + + if ((hFind = FindFirstFile(state->cwd, &data)) != INVALID_HANDLE_VALUE) { + int length = strlen(data.cFileName); + + if (length != ptr_length) { + state->cwd = (char *) realloc(state->cwd, state->cwd_length+length+1); + } + memcpy(&state->cwd[state->cwd_length], data.cFileName, length+1); + ptr_length = length; + FindClose(hFind); + } + } +#endif + state->cwd_length += ptr_length; } ptr = tsrm_strtok_r(NULL, TOKENIZER_STRING, &tok); } + free(free_path); + if (state->cwd_length == COPY_WHEN_ABSOLUTE(state->cwd)) { state->cwd = (char *) realloc(state->cwd, state->cwd_length+1+1); state->cwd[state->cwd_length] = DEFAULT_SLASH; state->cwd[state->cwd_length+1] = '\0'; state->cwd_length++; } - } else { - state->cwd = (char *) realloc(state->cwd, path_length+1); - memcpy(state->cwd, path, path_length+1); - state->cwd_length = path_length; } -#ifdef TSRM_WIN32 - if (new_path) { - free(new_path); - } -#endif - free(free_path); - if (use_realpath && CWDG(realpath_cache_size_limit)) { - realpath_cache_add(orig_path, orig_path_len, state->cwd, state->cwd_length, t TSRMLS_CC); + realpath_cache_add(path, path_length, state->cwd, state->cwd_length, t TSRMLS_CC); } if (verify_path && verify_path(state)) { diff --git a/tests/lang/bug38579.inc b/tests/lang/bug38579.inc new file mode 100755 index 0000000000..8ecc55824e --- /dev/null +++ b/tests/lang/bug38579.inc @@ -0,0 +1,3 @@ + diff --git a/tests/lang/bug38579.phpt b/tests/lang/bug38579.phpt new file mode 100755 index 0000000000..445296c222 --- /dev/null +++ b/tests/lang/bug38579.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #38579 (include_once() may include the same file twice) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +ok