Hi,

php_resolve_path does not exit if passed a stream wrapper, but instead
tries to find it in include_path.  This can cause really weird error
messages and breaks pecl/phar completely (and probably other stream
wrappers), so I added stream wrapper detection to the exit shunt in the
start of php_resolve_path.

The patch is otherwise the same as yesterday's.

Greg
Index: main/fopen_wrappers.c
===================================================================
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.7
diff -u -r1.175.2.3.2.13.2.7 fopen_wrappers.c
--- main/fopen_wrappers.c       5 Mar 2008 13:34:12 -0000       
1.175.2.3.2.13.2.7
+++ main/fopen_wrappers.c       8 Mar 2008 06:11:31 -0000
@@ -447,6 +447,9 @@
        char resolved_path[MAXPATHLEN];
        char trypath[MAXPATHLEN];
        char *ptr, *end;
+       php_stream_wrapper *wrapper;
+       const char *p;
+       int n = 0;
 
        if (!filename) {
                return NULL;
@@ -462,21 +465,52 @@
                        return NULL;
                }
        }
+       /* test for stream wrappers and return */
+       for (p = filename; p - filename < filename_length && (isalnum((int)*p) 
|| *p == '+' || *p == '-' || *p == '.'); p++) {
+               n++;
+       }
+
+       if (n < filename_length - 3 && (*p == ':') && (!strncmp("//", p+1, 2) 
|| ( filename_length > 4 && !memcmp("data", filename, 4)))) {
+               /* found stream wrapper, this is an absolute path until stream 
wrappers implement realpath */
+               return estrndup(filename, filename_length);
+       }
 
-       ptr = path;
+       ptr = (char *) path;
        while (ptr && *ptr) {
+               int len, is_stream_wrapper = 0, maybe_stream = 1;
+
                end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+#ifndef PHP_WIN32
+               /* search for stream wrapper */
+               if (end - ptr  <= 1) {
+                       maybe_stream = 0;
+                       goto not_stream;
+               }
+               for (p = ptr, n = 0; p < end && (isalnum((int)*p) || *p == '+' 
|| *p == '-' || *p == '.'); p++) {
+                       n++;
+               }
+
+               if (n == end - ptr && *p && !strncmp("//", p+1, 2)) {
+                       is_stream_wrapper = 1;
+                       /* seek to real end of include_path portion */
+                       end = strchr(end + 1, DEFAULT_DIR_SEPARATOR);
+               } else {
+                       maybe_stream = 0;
+               }
+not_stream:
+#endif
                if (end) {
                        if ((end-ptr) + 1 + filename_length + 1 >= MAXPATHLEN) {
                                ptr = end + 1;
                                continue;
                        }
                        memcpy(trypath, ptr, end-ptr);
+                       len = end-ptr;
                        trypath[end-ptr] = '/';
                        memcpy(trypath+(end-ptr)+1, filename, 
filename_length+1);
                        ptr = end+1;
                } else {
-                       int len = strlen(ptr);
+                       len = strlen(ptr);
 
                        if (len + 1 + filename_length + 1 >= MAXPATHLEN) {
                                break;
@@ -486,6 +520,35 @@
                        memcpy(trypath+len+1, filename, filename_length+1);
                        ptr = NULL;
                }
+
+               if (!is_stream_wrapper && maybe_stream) {
+                       /* search for stream wrapper */
+                       for (p = trypath; isalnum((int)*p) || *p == '+' || *p 
== '-' || *p == '.'; p++) {
+                               n++;
+                       }
+               }
+
+               if (is_stream_wrapper || (n < len - 3 && (*p == ':') && (n > 1) 
&& (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4)))) {
+                       char *actual;
+
+                       wrapper = php_stream_locate_url_wrapper(trypath, 
&actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
+                       if (wrapper == &php_plain_files_wrapper) {
+                               strncpy(trypath, actual, MAXPATHLEN);
+                       } else if (!wrapper) {
+                               /* if wrapper is NULL, there was a mal-formed 
include_path stream wrapper, so skip this ptr */
+                               continue;
+                       } else {
+                               if (wrapper->wops->url_stat) {
+                                       php_stream_statbuf ssb;
+
+                                       if (SUCCESS == 
wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL TSRMLS_CC)) {
+                                               return estrdup(trypath);
+                                       }
+                               }
+                               continue;
+                       }
+               }
+
                if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
                        return estrdup(resolved_path);
                }
@@ -496,6 +559,8 @@
        if (zend_is_executing(TSRMLS_C)) {
                char *exec_fname = zend_get_executed_filename(TSRMLS_C);
                int exec_fname_length = strlen(exec_fname);
+               const char *p;
+               int n = 0;
 
                while ((--exec_fname_length >= 0) && 
!IS_SLASH(exec_fname[exec_fname_length]));
                if (exec_fname && exec_fname[0] != '[' &&
@@ -503,6 +568,26 @@
                    exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) {
                        memcpy(trypath, exec_fname, exec_fname_length + 1);
                        memcpy(trypath+exec_fname_length + 1, filename, 
filename_length+1);
+
+                       /* search for stream wrapper */
+                       for (p = trypath; isalnum((int)*p) || *p == '+' || *p 
== '-' || *p == '.'; p++) {
+                               n++;
+                       }
+                       if (n < exec_fname_length - 3 && (*p == ':') && (n > 1) 
&& (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4))) {
+                               char *actual;
+       
+                               wrapper = 
php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+                               if (wrapper == &php_plain_files_wrapper) {
+                                       /* this should never technically 
happen, but we'll leave it here for completeness */
+                                       strncpy(trypath, actual, MAXPATHLEN);
+                               } else if (!wrapper) {
+                                       /* if wrapper is NULL, there was a 
mal-formed include_path stream wrapper
+                                          this also should be impossible */
+                                       return NULL;
+                               } else {
+                                       return estrdup(trypath);
+                               }
+                       }
                        if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
                                return estrdup(resolved_path);
                        }
Index: main/main.c
===================================================================
RCS file: /repository/php-src/main/main.c,v
retrieving revision 1.640.2.23.2.57.2.11
diff -u -r1.640.2.23.2.57.2.11 main.c
--- main/main.c 5 Mar 2008 13:34:12 -0000       1.640.2.23.2.57.2.11
+++ main/main.c 8 Mar 2008 06:11:32 -0000
@@ -1077,8 +1077,15 @@
 PHPAPI int php_stream_open_for_zend_ex(const char *filename, zend_file_handle 
*handle, int mode TSRMLS_DC) /* {{{ */
 {
        php_stream *stream;
+       char *resolved_path;
 
-       stream = php_stream_open_wrapper((char *)filename, "rb", mode, 
&handle->opened_path);
+       resolved_path = zend_resolve_path((char *)filename, strlen(filename) 
TSRMLS_CC);
+       if (resolved_path) {
+               stream = php_stream_open_wrapper(resolved_path, "rb", mode, 
&handle->opened_path);
+               efree(resolved_path);
+       } else {
+               stream = php_stream_open_wrapper((char *)filename, "rb", mode, 
&handle->opened_path);
+       }
 
        if (stream) {
                handle->type = ZEND_HANDLE_STREAM;

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to