mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
MFH Fix for Bug #21310
This commit is contained in:
parent
25e8d3215d
commit
03777d2784
@ -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);
|
||||
@ -363,58 +366,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--;
|
||||
}
|
||||
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);
|
||||
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)) {
|
||||
|
14
acinclude.m4
14
acinclude.m4
@ -1448,6 +1448,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,[
|
||||
|
@ -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.
|
||||
|
18
main/main.c
18
main/main.c
@ -1568,7 +1568,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;
|
||||
|
||||
@ -1576,9 +1580,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
|
||||
@ -1589,7 +1595,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);
|
||||
}
|
||||
|
||||
@ -1641,10 +1652,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;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -125,6 +125,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 */
|
||||
|
Loading…
Reference in New Issue
Block a user