diff options
author | Wez Furlong <wez@php.net> | 2003-03-17 13:40:45 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2003-03-17 13:40:45 +0000 |
commit | cfd0466389aaa2d3ff2068fb87b7a65128c3db3e (patch) | |
tree | c6d02f5ed4438388c175811dc816950de58c5fe7 | |
parent | dbe4f2238ceed386a69cacbbce5cae8b0a856fab (diff) | |
download | php-git-cfd0466389aaa2d3ff2068fb87b7a65128c3db3e.tar.gz |
Fix for Bug #21310, based on a patch by jflemer@php.net.
-rw-r--r-- | TSRM/tsrm_virtual_cwd.c | 93 | ||||
-rw-r--r-- | acinclude.m4 | 14 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | main/main.c | 18 | ||||
-rw-r--r-- | main/safe_mode.c | 5 |
5 files changed, 88 insertions, 43 deletions
diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c index 082cdf96a5..d62745ad32 100644 --- a/TSRM/tsrm_virtual_cwd.c +++ b/TSRM/tsrm_virtual_cwd.c @@ -303,7 +303,10 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func return (0); #if !defined(TSRM_WIN32) && !defined(NETWARE) - if (IS_ABSOLUTE_PATH(path, path_length)) { + /* 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 && realpath(path, resolved_path)) { path = resolved_path; path_length = strlen(path); @@ -360,58 +363,64 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func } - ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok); - while (ptr) { - ptr_length = strlen(ptr); + if (state->cwd_length > 0 || IS_ABSOLUTE_PATH(path, path_length)) { + ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok); + while (ptr) { + ptr_length = strlen(ptr); - if (IS_DIRECTORY_UP(ptr, ptr_length)) { - char save; + if (IS_DIRECTORY_UP(ptr, ptr_length)) { + char save; - save = DEFAULT_SLASH; + save = DEFAULT_SLASH; #define PREVIOUS state->cwd[state->cwd_length - 1] - while (IS_ABSOLUTE_PATH(state->cwd, state->cwd_length) && - !IS_SLASH(PREVIOUS)) { - save = PREVIOUS; - PREVIOUS = '\0'; - state->cwd_length--; - } - - if (!IS_ABSOLUTE_PATH(state->cwd, state->cwd_length)) { - state->cwd[state->cwd_length++] = save; - state->cwd[state->cwd_length] = '\0'; - } else { - PREVIOUS = '\0'; - state->cwd_length--; - } - } else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) { - state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1+1); + while (IS_ABSOLUTE_PATH(state->cwd, state->cwd_length) && + !IS_SLASH(PREVIOUS)) { + save = PREVIOUS; + PREVIOUS = '\0'; + state->cwd_length--; + } + + if (!IS_ABSOLUTE_PATH(state->cwd, state->cwd_length)) { + state->cwd[state->cwd_length++] = save; + state->cwd[state->cwd_length] = '\0'; + } else { + PREVIOUS = '\0'; + state->cwd_length--; + } + } else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) { + 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]!='/') || - IsDBCSLeadByte(state->cwd[state->cwd_length-2])) { - state->cwd[state->cwd_length++] = DEFAULT_SLASH; - } + /* 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]!='/') || + IsDBCSLeadByte(state->cwd[state->cwd_length-2])) { + state->cwd[state->cwd_length++] = DEFAULT_SLASH; + } #elif defined(NETWARE) - /* If the token is a volume name, it will have colon at the end -- so, no slash before it */ - if (ptr[ptr_length-1] != ':') { - state->cwd[state->cwd_length++] = DEFAULT_SLASH; - } + /* If the token is a volume name, it will have colon at the end -- so, no slash before it */ + if (ptr[ptr_length-1] != ':') { + state->cwd[state->cwd_length++] = DEFAULT_SLASH; + } #else - state->cwd[state->cwd_length++] = DEFAULT_SLASH; + state->cwd[state->cwd_length++] = DEFAULT_SLASH; #endif - memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1); - state->cwd_length += ptr_length; + memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1); + state->cwd_length += ptr_length; + } + ptr = tsrm_strtok_r(NULL, TOKENIZER_STRING, &tok); } - ptr = tsrm_strtok_r(NULL, TOKENIZER_STRING, &tok); - } - 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++; + 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; } if (verify_path && verify_path(state)) { diff --git a/acinclude.m4 b/acinclude.m4 index fd616da1ec..0971796bbf 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1441,6 +1441,20 @@ int main(void) { fi ]) +dnl Some systems, notably Solaris, cause getcwd() or realpath to fail if a +dnl component of the path has execute but not read permissions +AC_DEFUN([PHP_BROKEN_GETCWD],[ + AC_MSG_CHECKING([for broken getcwd]) + os=`uname -sr 2>/dev/null` + case $os in + SunOS*) + AC_DEFINE(HAVE_BROKEN_GETCWD,1, [Define if system has broken getcwd]) + AC_MSG_RESULT([yes]);; + *) + AC_MSG_RESULT([no]);; + esac +]) + AC_DEFUN([PHP_BROKEN_GLIBC_FOPEN_APPEND],[ AC_MSG_CHECKING([for broken libc stdio]) AC_CACHE_VAL(have_broken_glibc_fopen_append,[ diff --git a/configure.in b/configure.in index bd46c8e96b..2d0c367159 100644 --- a/configure.in +++ b/configure.in @@ -378,6 +378,7 @@ sys/ipc.h \ ]) PHP_FOPENCOOKIE +PHP_BROKEN_GETCWD PHP_BROKEN_GLIBC_FOPEN_APPEND dnl Checks for typedefs, structures, and compiler characteristics. diff --git a/main/main.c b/main/main.c index f98de09e9e..99a17b9ebf 100644 --- a/main/main.c +++ b/main/main.c @@ -1507,7 +1507,11 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC) { zend_file_handle *prepend_file_p, *append_file_p; zend_file_handle prepend_file, append_file; +#if HAVE_BROKEN_GETCWD + int old_cwd_fd; +#else char *old_cwd; +#endif char *old_primary_file_path = NULL; int retval = 0; @@ -1515,9 +1519,11 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC) if (php_handle_special_queries(TSRMLS_C)) { return 0; } -#define OLD_CWD_SIZE 4096 +#ifndef HAVE_BROKEN_GETCWD +# define OLD_CWD_SIZE 4096 old_cwd = do_alloca(OLD_CWD_SIZE); old_cwd[0] = '\0'; +#endif zend_try { #ifdef PHP_WIN32 @@ -1528,7 +1534,12 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC) if (primary_file->type == ZEND_HANDLE_FILENAME && primary_file->filename) { +#if HAVE_BROKEN_GETCWD + /* this looks nasty to me */ + old_cwd_fd = open(".", 0); +#else VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1); +#endif VCWD_CHDIR_FILE(primary_file->filename); } @@ -1580,10 +1591,15 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC) } zend_end_try(); +#if HAVE_BROKEN_GETCWD + fchdir(old_cwd_fd); + close(old_cwd_fd); +#else if (old_cwd[0] != '\0') { VCWD_CHDIR(old_cwd); } free_alloca(old_cwd); +#endif return retval; } /* }}} */ diff --git a/main/safe_mode.c b/main/safe_mode.c index 4c21cb49d7..c7e3fd7abe 100644 --- a/main/safe_mode.c +++ b/main/safe_mode.c @@ -126,6 +126,11 @@ PHPAPI int php_checkuid_ex(const char *filename, char *fopen_mode, int mode, int VCWD_REALPATH(filename, path); *s = DEFAULT_SLASH; } else { + /* Under Solaris, getcwd() can fail if there are no + * read permissions on a component of the path, even + * though it has the required x permissions */ + path[0] = '.'; + path[1] = '\0'; VCWD_GETCWD(path, sizeof(path)); } } /* end CHECKUID_ALLOW_ONLY_DIR */ |