Patch: Rasmus statcallpatch with configure option
| From: | Derick Rethans | Date: | Tue, 14 Sep 2004 12:10:52 +0000 |
| Subject: | Patch: Rasmus statcallpatch with configure option | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-12793@lists.php.net to get a copy of this message | ||
Hei,
This is Rasmus' patch including a configure option
"--disable-path-normalization" to enable this patch. By default this
option is of course turned off.
I am planning to commit this patch after 4.3.9 is released too, in case
there are no good objections.
Derick
--
Derick Rethans
http://derickrethans.nl | http://ez.no | http://xdebug.org
Index: configure.in =================================================================== RCS file: /repository/php-src/configure.in,v retrieving revision 1.396.2.125 diff -u -p -r1.396.2.125 configure.in --- configure.in 14 Sep 2004 04:33:09 -0000 1.396.2.125 +++ configure.in 14 Sep 2004 11:55:09 -0000 @@ -748,6 +748,13 @@ if test "$PHP_IPV6" != "no" && test "$ac AC_DEFINE(HAVE_IPV6,1,[Whether to enable IPv6 support]) fi +PHP_ARG_ENABLE(path-normalization,whether to enable path normalization, +[ --disable-path-normalization + Disable path normalization], yes, no) +if test "$PHP_PATH_NORMALIZATION" == "no"; then + AC_DEFINE(SKIP_PATH_CHECKS,1,[Whether to disable path normalization]) +fi + AC_MSG_CHECKING([whether to enable versioning]) AC_ARG_ENABLE(versioning, [ --enable-versioning Export only required symbols. Index: Zend/zend_language_scanner.l =================================================================== RCS file: /repository/Zend/Attic/zend_language_scanner.l,v retrieving revision 1.54.2.26 diff -u -p -r1.54.2.26 zend_language_scanner.l --- Zend/zend_language_scanner.l 3 Feb 2004 14:31:19 -0000 1.54.2.26 +++ Zend/zend_language_scanner.l 14 Sep 2004 11:55:10 -0000 @@ -41,6 +41,7 @@ %x ST_COMMENT %x ST_ONE_LINE_COMMENT %option stack +%option never-interactive %{ Index: main/fopen_wrappers.c =================================================================== RCS file: /repository/php-src/main/fopen_wrappers.c,v retrieving revision 1.153.2.9 diff -u -p -r1.153.2.9 fopen_wrappers.c --- main/fopen_wrappers.c 16 Mar 2004 00:32:09 -0000 1.153.2.9 +++ main/fopen_wrappers.c 14 Sep 2004 11:55:11 -0000 @@ -106,7 +106,9 @@ PHPAPI int php_check_specific_open_based char resolved_name[MAXPATHLEN]; char resolved_basedir[MAXPATHLEN]; char local_open_basedir[MAXPATHLEN]; + char local_path[MAXPATHLEN]; int local_open_basedir_pos; + int local_path_pos; int resolved_basedir_len; int resolved_name_len; @@ -128,9 +130,30 @@ PHPAPI int php_check_specific_open_based strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir)); } +#ifdef SKIP_PATH_CHECKS + if ( path[0] == '.' && path[1] == '/' && SG(request_info).path_translated && *SG(request_info).path_translated ) { + strlcpy(local_path, SG(request_info).path_translated, sizeof(local_path) ); + local_path_pos = strlen(local_path) - 1; + + /* Strip filename */ + while (!IS_SLASH(local_path[local_path_pos]) && (local_path_pos >= 0)) { + local_path[local_path_pos--] = 0; + } + + strncat( local_path, path + 2, MAXPATHLEN - (local_path_pos + strlen( path )) ); + } + else { +#endif + /* Else use the unmodified path */ + strlcpy(local_path, path, sizeof(local_path)); +#ifdef SKIP_PATH_CHECKS + } + if(strstr(local_path,"..")) return -1; +#endif + /* Resolve the real path into resolved_name */ - if ((expand_filepath(path, resolved_name TSRMLS_CC) != NULL) && (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL)) { - /* Handler for basedirs that end with a / */ + if ((expand_filepath(local_path, resolved_name TSRMLS_CC) != NULL) && (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL)) { + /* Handler for basedirs that end with a / */ resolved_basedir_len = strlen(resolved_basedir); if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) { if (resolved_basedir[resolved_basedir_len - 1] == '/') { @@ -139,7 +162,7 @@ PHPAPI int php_check_specific_open_based } } - if (path[strlen(path)-1] == PHP_DIR_SEPARATOR) { + if (local_path[strlen(local_path)-1] == PHP_DIR_SEPARATOR) { resolved_name_len = strlen(resolved_name); if (resolved_name[resolved_name_len - 1] != PHP_DIR_SEPARATOR) { resolved_name[resolved_name_len] = PHP_DIR_SEPARATOR; @@ -533,6 +556,16 @@ PHPAPI char *php_strip_url_passwd(char * */ PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC) { +#ifdef SKIP_PATH_CHECKS + int len = strlen(filepath); + + if(filepath[len-1] == PHP_DIR_SEPARATOR) len--; + if(!real_path) real_path = estrdup(filepath); + else strcpy(real_path, filepath); + real_path[len]='\0'; + + return real_path; +#else cwd_state new_state; char cwd[MAXPATHLEN]; char *result; @@ -558,8 +591,8 @@ PHPAPI char *expand_filepath(const char real_path = estrndup(new_state.cwd, new_state.cwd_length); } free(new_state.cwd); - return real_path; +#endif } /* }}} */ Index: main/main.c =================================================================== RCS file: /repository/php-src/main/main.c,v retrieving revision 1.512.2.55 diff -u -p -r1.512.2.55 main.c --- main/main.c 16 Aug 2004 12:23:06 -0000 1.512.2.55 +++ main/main.c 14 Sep 2004 11:55:12 -0000 @@ -1696,9 +1696,13 @@ PHPAPI int php_execute_script(zend_file_ } if (primary_file->filename) { + int dummy = 1; +#ifdef SKIP_PATH_CHECKS + zend_hash_add(&EG(included_files), primary_file->filename, strlen(primary_file->filename)+1, (void *)&dummy, sizeof(int), NULL); +#else char realfile[MAXPATHLEN]; int realfile_len; - int dummy = 1; + if (VCWD_REALPATH(primary_file->filename, realfile)) { realfile_len = strlen(realfile); zend_hash_add(&EG(included_files), realfile, realfile_len+1, (void *)&dummy, sizeof(int), NULL); @@ -1707,6 +1711,7 @@ PHPAPI int php_execute_script(zend_file_ primary_file->filename = realfile; } } +#endif } if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) { Index: main/streams.c =================================================================== RCS file: /repository/php-src/main/Attic/streams.c,v retrieving revision 1.125.2.93 diff -u -p -r1.125.2.93 streams.c --- main/streams.c 31 Aug 2004 15:32:09 -0000 1.125.2.93 +++ main/streams.c 14 Sep 2004 11:55:12 -0000 @@ -1398,6 +1398,7 @@ PHPAPI php_stream *_php_stream_fopen_fro self->temp_file_name = NULL; self->fd = fileno(file); +#ifndef SKIP_PATH_CHECKS #ifdef S_ISFIFO /* detect if this is a pipe */ if (self->fd >= 0) { @@ -1405,6 +1406,7 @@ PHPAPI php_stream *_php_stream_fopen_fro self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0; } #endif +#endif stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode); @@ -1417,9 +1419,12 @@ PHPAPI php_stream *_php_stream_fopen_fro if (stream) { if (self->is_pipe) { stream->flags |= PHP_STREAM_FLAG_NO_SEEK | PHP_STREAM_FLAG_AVOID_BLOCKING; - } else { + } +#if 0 + else { stream->position = ftell(file); } +#endif } return stream; @@ -1986,6 +1991,7 @@ PHPAPI php_stream *_php_stream_fopen(con fd = open(realpath, open_flags, 0666); if (fd != -1) { +#ifndef SKIP_PATH_CHECKS /* sanity checks for include/require */ if (options & STREAM_OPEN_FOR_INCLUDE && (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode))) { #ifdef PHP_WIN32 @@ -1995,6 +2001,7 @@ PHPAPI php_stream *_php_stream_fopen(con #endif goto err; } +#endif ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id); @@ -2049,10 +2056,12 @@ PHPAPI php_stream *_php_stream_fopen_fro self->fd = fd; #ifdef S_ISFIFO +#ifndef SKIP_PATH_CHECKS /* detect if this is a pipe */ if (stat_ok) { self->is_pipe = S_ISFIFO(sb.st_mode) ? 1 : 0; } +#endif #elif defined(PHP_WIN32) { long handle = _get_osfhandle(self->fd); @@ -2066,6 +2075,7 @@ PHPAPI php_stream *_php_stream_fopen_fro stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode); +#ifndef SKIP_PATH_CHECKS if (stream) { if (self->is_pipe) { stream->flags |= PHP_STREAM_FLAG_NO_SEEK | PHP_STREAM_FLAG_AVOID_BLOCKING; @@ -2073,6 +2083,7 @@ PHPAPI php_stream *_php_stream_fopen_fro stream->position = lseek(self->fd, 0, SEEK_CUR); } } +#endif return stream; } @@ -2176,12 +2187,14 @@ PHPAPI int _php_stream_cast(php_stream * /* synchronize our buffer (if possible) */ if (ret && castas != PHP_STREAM_AS_FD_FOR_SELECT) { php_stream_flush(stream); +#ifndef SKIP_PATH_CHECKS if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) { off_t dummy; stream->ops->seek(stream, stream->position, SEEK_SET, &dummy TSRMLS_CC); stream->readpos = stream->writepos = 0; } +#endif } /* filtered streams can only be cast as stdio, and only when fopencookie is present */
Index: configure.in =================================================================== RCS file: /repository/php-src/configure.in,v retrieving revision 1.396.2.125 diff -u -p -r1.396.2.125 configure.in --- configure.in 14 Sep 2004 04:33:09 -0000 1.396.2.125 +++ configure.in 14 Sep 2004 11:55:09 -0000 @@ -748,6 +748,13 @@ if test "$PHP_IPV6" != "no" && test "$ac AC_DEFINE(HAVE_IPV6,1,[Whether to enable IPv6 support]) fi +PHP_ARG_ENABLE(path-normalization,whether to enable path normalization, +[ --disable-path-normalization + Disable path normalization], yes, no) +if test "$PHP_PATH_NORMALIZATION" == "no"; then + AC_DEFINE(SKIP_PATH_CHECKS,1,[Whether to disable path normalization]) +fi + AC_MSG_CHECKING([whether to enable versioning]) AC_ARG_ENABLE(versioning, [ --enable-versioning Export only required symbols. Index: Zend/zend_language_scanner.l =================================================================== RCS file: /repository/Zend/Attic/zend_language_scanner.l,v retrieving revision 1.54.2.26 diff -u -p -r1.54.2.26 zend_language_scanner.l --- Zend/zend_language_scanner.l 3 Feb 2004 14:31:19 -0000 1.54.2.26 +++ Zend/zend_language_scanner.l 14 Sep 2004 11:55:10 -0000 @@ -41,6 +41,7 @@ %x ST_COMMENT %x ST_ONE_LINE_COMMENT %option stack +%option never-interactive %{ Index: main/fopen_wrappers.c =================================================================== RCS file: /repository/php-src/main/fopen_wrappers.c,v retrieving revision 1.153.2.9 diff -u -p -r1.153.2.9 fopen_wrappers.c --- main/fopen_wrappers.c 16 Mar 2004 00:32:09 -0000 1.153.2.9 +++ main/fopen_wrappers.c 14 Sep 2004 11:55:11 -0000 @@ -106,7 +106,9 @@ PHPAPI int php_check_specific_open_based char resolved_name[MAXPATHLEN]; char resolved_basedir[MAXPATHLEN]; char local_open_basedir[MAXPATHLEN]; + char local_path[MAXPATHLEN]; int local_open_basedir_pos; + int local_path_pos; int resolved_basedir_len; int resolved_name_len; @@ -128,9 +130,30 @@ PHPAPI int php_check_specific_open_based strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir)); } +#ifdef SKIP_PATH_CHECKS + if ( path[0] == '.' && path[1] == '/' && SG(request_info).path_translated && *SG(request_info).path_translated ) { + strlcpy(local_path, SG(request_info).path_translated, sizeof(local_path) ); + local_path_pos = strlen(local_path) - 1; + + /* Strip filename */ + while (!IS_SLASH(local_path[local_path_pos]) && (local_path_pos >= 0)) { + local_path[local_path_pos--] = 0; + } + + strncat( local_path, path + 2, MAXPATHLEN - (local_path_pos + strlen( path )) ); + } + else { +#endif + /* Else use the unmodified path */ + strlcpy(local_path, path, sizeof(local_path)); +#ifdef SKIP_PATH_CHECKS + } + if(strstr(local_path,"..")) return -1; +#endif + /* Resolve the real path into resolved_name */ - if ((expand_filepath(path, resolved_name TSRMLS_CC) != NULL) && (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL)) { - /* Handler for basedirs that end with a / */ + if ((expand_filepath(local_path, resolved_name TSRMLS_CC) != NULL) && (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL)) { + /* Handler for basedirs that end with a / */ resolved_basedir_len = strlen(resolved_basedir); if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) { if (resolved_basedir[resolved_basedir_len - 1] == '/') { @@ -139,7 +162,7 @@ PHPAPI int php_check_specific_open_based } } - if (path[strlen(path)-1] == PHP_DIR_SEPARATOR) { + if (local_path[strlen(local_path)-1] == PHP_DIR_SEPARATOR) { resolved_name_len = strlen(resolved_name); if (resolved_name[resolved_name_len - 1] != PHP_DIR_SEPARATOR) { resolved_name[resolved_name_len] = PHP_DIR_SEPARATOR; @@ -533,6 +556,16 @@ PHPAPI char *php_strip_url_passwd(char * */ PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC) { +#ifdef SKIP_PATH_CHECKS + int len = strlen(filepath); + + if(filepath[len-1] == PHP_DIR_SEPARATOR) len--; + if(!real_path) real_path = estrdup(filepath); + else strcpy(real_path, filepath); + real_path[len]='\0'; + + return real_path; +#else cwd_state new_state; char cwd[MAXPATHLEN]; char *result; @@ -558,8 +591,8 @@ PHPAPI char *expand_filepath(const char real_path = estrndup(new_state.cwd, new_state.cwd_length); } free(new_state.cwd); - return real_path; +#endif } /* }}} */ Index: main/main.c =================================================================== RCS file: /repository/php-src/main/main.c,v retrieving revision 1.512.2.55 diff -u -p -r1.512.2.55 main.c --- main/main.c 16 Aug 2004 12:23:06 -0000 1.512.2.55 +++ main/main.c 14 Sep 2004 11:55:12 -0000 @@ -1696,9 +1696,13 @@ PHPAPI int php_execute_script(zend_file_ } if (primary_file->filename) { + int dummy = 1; +#ifdef SKIP_PATH_CHECKS + zend_hash_add(&EG(included_files), primary_file->filename, strlen(primary_file->filename)+1, (void *)&dummy, sizeof(int), NULL); +#else char realfile[MAXPATHLEN]; int realfile_len; - int dummy = 1; + if (VCWD_REALPATH(primary_file->filename, realfile)) { realfile_len = strlen(realfile); zend_hash_add(&EG(included_files), realfile, realfile_len+1, (void *)&dummy, sizeof(int), NULL); @@ -1707,6 +1711,7 @@ PHPAPI int php_execute_script(zend_file_ primary_file->filename = realfile; } } +#endif } if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) { Index: main/streams.c =================================================================== RCS file: /repository/php-src/main/Attic/streams.c,v retrieving revision 1.125.2.93 diff -u -p -r1.125.2.93 streams.c --- main/streams.c 31 Aug 2004 15:32:09 -0000 1.125.2.93 +++ main/streams.c 14 Sep 2004 11:55:12 -0000 @@ -1398,6 +1398,7 @@ PHPAPI php_stream *_php_stream_fopen_fro self->temp_file_name = NULL; self->fd = fileno(file); +#ifndef SKIP_PATH_CHECKS #ifdef S_ISFIFO /* detect if this is a pipe */ if (self->fd >= 0) { @@ -1405,6 +1406,7 @@ PHPAPI php_stream *_php_stream_fopen_fro self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0; } #endif +#endif stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode); @@ -1417,9 +1419,12 @@ PHPAPI php_stream *_php_stream_fopen_fro if (stream) { if (self->is_pipe) { stream->flags |= PHP_STREAM_FLAG_NO_SEEK | PHP_STREAM_FLAG_AVOID_BLOCKING; - } else { + } +#if 0 + else { stream->position = ftell(file); } +#endif } return stream; @@ -1986,6 +1991,7 @@ PHPAPI php_stream *_php_stream_fopen(con fd = open(realpath, open_flags, 0666); if (fd != -1) { +#ifndef SKIP_PATH_CHECKS /* sanity checks for include/require */ if (options & STREAM_OPEN_FOR_INCLUDE && (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode))) { #ifdef PHP_WIN32 @@ -1995,6 +2001,7 @@ PHPAPI php_stream *_php_stream_fopen(con #endif goto err; } +#endif ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id); @@ -2049,10 +2056,12 @@ PHPAPI php_stream *_php_stream_fopen_fro self->fd = fd; #ifdef S_ISFIFO +#ifndef SKIP_PATH_CHECKS /* detect if this is a pipe */ if (stat_ok) { self->is_pipe = S_ISFIFO(sb.st_mode) ? 1 : 0; } +#endif #elif defined(PHP_WIN32) { long handle = _get_osfhandle(self->fd); @@ -2066,6 +2075,7 @@ PHPAPI php_stream *_php_stream_fopen_fro stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode); +#ifndef SKIP_PATH_CHECKS if (stream) { if (self->is_pipe) { stream->flags |= PHP_STREAM_FLAG_NO_SEEK | PHP_STREAM_FLAG_AVOID_BLOCKING; @@ -2073,6 +2083,7 @@ PHPAPI php_stream *_php_stream_fopen_fro stream->position = lseek(self->fd, 0, SEEK_CUR); } } +#endif return stream; } @@ -2176,12 +2187,14 @@ PHPAPI int _php_stream_cast(php_stream * /* synchronize our buffer (if possible) */ if (ret && castas != PHP_STREAM_AS_FD_FOR_SELECT) { php_stream_flush(stream); +#ifndef SKIP_PATH_CHECKS if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) { off_t dummy; stream->ops->seek(stream, stream->position, SEEK_SET, &dummy TSRMLS_CC); stream->readpos = stream->writepos = 0; } +#endif } /* filtered streams can only be cast as stdio, and only when fopencookie is present */