]> granicus.if.org Git - php/commitdiff
Improve SPL directory and stat() cache using zend_srting* instead of char*
authorDmitry Stogov <dmitry@zend.com>
Thu, 25 Feb 2021 23:28:46 +0000 (02:28 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 25 Feb 2021 23:28:46 +0000 (02:28 +0300)
13 files changed:
ext/phar/phar_object.c
ext/spl/spl_directory.c
ext/spl/spl_directory.h
ext/standard/basic_functions.h
ext/standard/dir.c
ext/standard/file.c
ext/standard/filestat.c
ext/standard/php_filestat.h
ext/zip/php_zip.c
main/php_streams.h
main/streams/plain_wrapper.c
main/streams/streams.c
sapi/phpdbg/phpdbg_wait.c

index 07c5abd198a7aa16595eed2e3212058002b64c2d..2100356d9b40c79eeed883e19dcbb1dbf5b6844e 100644 (file)
@@ -1443,7 +1443,6 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
                case IS_OBJECT:
                        if (instanceof_function(Z_OBJCE_P(value), spl_ce_SplFileInfo)) {
                                char *test = NULL;
-                               zval dummy;
                                spl_filesystem_object *intern = (spl_filesystem_object*)((char*)Z_OBJ_P(value) - Z_OBJ_P(value)->handlers->offset);
 
                                if (!base_len) {
@@ -1455,9 +1454,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
                                        case SPL_FS_DIR:
                                                test = spl_filesystem_object_get_path(intern, NULL);
                                                fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
-                                               php_stat(fname, fname_len, FS_IS_DIR, &dummy);
-
-                                               if (Z_TYPE(dummy) == IS_TRUE) {
+                                               if (php_stream_stat_path(fname, &ssb) == 0 && S_ISDIR(ssb.sb.st_mode)) {
                                                        /* ignore directories */
                                                        efree(fname);
                                                        return ZEND_HASH_APPLY_KEEP;
@@ -1478,7 +1475,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
                                                goto phar_spl_fileinfo;
                                        case SPL_FS_INFO:
                                        case SPL_FS_FILE:
-                                               fname = expand_filepath(intern->file_name, NULL);
+                                               fname = expand_filepath(ZSTR_VAL(intern->file_name), NULL);
                                                if (!fname) {
                                                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
                                                        return ZEND_HASH_APPLY_STOP;
@@ -4644,11 +4641,11 @@ PHP_METHOD(PharFileInfo, chmod)
        /* hackish cache in php_stat needs to be cleared */
        /* if this code fails to work, check main/streams/streams.c, _php_stream_stat_path */
        if (BG(CurrentLStatFile)) {
-               efree(BG(CurrentLStatFile));
+               zend_string_release(BG(CurrentLStatFile));
        }
 
        if (BG(CurrentStatFile)) {
-               efree(BG(CurrentStatFile));
+               zend_string_release(BG(CurrentStatFile));
        }
 
        BG(CurrentLStatFile) = NULL;
index c26cd1aa89351085c979e104652019a031ef4d6a..cd796ae048a0f5fbca189b6adb2b1564909c176d 100644 (file)
@@ -114,18 +114,18 @@ static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
 
        zend_object_std_dtor(&intern->std);
 
-       if (intern->_path) {
-               efree(intern->_path);
+       if (intern->path) {
+               zend_string_release(intern->path);
        }
        if (intern->file_name) {
-               efree(intern->file_name);
+               zend_string_release(intern->file_name);
        }
        switch(intern->type) {
        case SPL_FS_INFO:
                break;
        case SPL_FS_DIR:
                if (intern->u.dir.sub_path) {
-                       efree(intern->u.dir.sub_path);
+                       zend_string_release(intern->u.dir.sub_path);
                }
                break;
        case SPL_FS_FILE:
@@ -133,7 +133,7 @@ static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
                        efree(intern->u.file.open_mode);
                }
                if (intern->orig_path) {
-                       efree(intern->orig_path);
+                       zend_string_release(intern->orig_path);
                }
                spl_filesystem_file_free_line(intern);
                break;
@@ -195,9 +195,9 @@ PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_
        }
 #endif
        if (len) {
-               *len = intern->_path_len;
+               *len = intern->path ? ZSTR_LEN(intern->path) : 0;
        }
-       return intern->_path;
+       return intern->path ? ZSTR_VAL(intern->path) : NULL;
 } /* }}} */
 
 static inline int spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */
@@ -217,15 +217,15 @@ static inline int spl_filesystem_object_get_file_name(spl_filesystem_object *int
                                size_t path_len = 0;
                                char *path = spl_filesystem_object_get_path(intern, &path_len);
                                if (intern->file_name) {
-                                       efree(intern->file_name);
+                                       zend_string_release(intern->file_name);
                                }
                                /* if there is parent path, amend it, otherwise just use the given path as is */
                                if (path_len == 0) {
-                                       intern->file_name_len = spprintf(
-                                               &intern->file_name, 0, "%s", intern->u.dir.entry.d_name);
+                                       intern->file_name = zend_strpprintf(
+                                               0, "%s", intern->u.dir.entry.d_name);
                                } else {
-                                       intern->file_name_len = spprintf(
-                                               &intern->file_name, 0, "%s%c%s", path, slash, intern->u.dir.entry.d_name);
+                                       intern->file_name = zend_strpprintf(
+                                               0, "%s%c%s", path, slash, intern->u.dir.entry.d_name);
                                }
                        }
                        break;
@@ -254,18 +254,17 @@ static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */
 
 /* {{{ spl_filesystem_dir_open */
 /* open a directory resource */
-static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path)
+static void spl_filesystem_dir_open(spl_filesystem_object* intern, zend_string *path)
 {
        int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
 
        intern->type = SPL_FS_DIR;
-       intern->_path_len = strlen(path);
-       intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context));
+       intern->u.dir.dirp = php_stream_opendir(ZSTR_VAL(path), REPORT_ERRORS, FG(default_context));
 
-       if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) {
-               intern->_path = estrndup(path, --intern->_path_len);
+       if (ZSTR_LEN(path) > 1 && IS_SLASH_AT(ZSTR_VAL(path), ZSTR_LEN(path)-1)) {
+               intern->path = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path)-1, 0);
        } else {
-               intern->_path = estrndup(path, intern->_path_len);
+               intern->path = zend_string_copy(path);
        }
        intern->u.dir.index = 0;
 
@@ -274,7 +273,7 @@ static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path)
                if (!EG(exception)) {
                        /* open failed w/out notice (turned to exception due to EH_THROW) */
                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
-                               "Failed to open directory \"%s\"", path);
+                               "Failed to open directory \"%s\"", ZSTR_VAL(path));
                }
        } else {
                do {
@@ -289,8 +288,7 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu
        zval tmp;
 
        intern->type = SPL_FS_FILE;
-
-       php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, &tmp);
+       php_stat(intern->file_name, FS_IS_DIR, &tmp);
        if (Z_TYPE(tmp) == IS_TRUE) {
                intern->u.file.open_mode = NULL;
                intern->file_name = NULL;
@@ -299,11 +297,11 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu
        }
 
        intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0);
-       intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, intern->u.file.context);
+       intern->u.file.stream = php_stream_open_wrapper_ex(ZSTR_VAL(intern->file_name), intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, intern->u.file.context);
 
-       if (!intern->file_name_len || !intern->u.file.stream) {
+       if (!ZSTR_LEN(intern->file_name) || !intern->u.file.stream) {
                if (!EG(exception)) {
-                       zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", intern->file_name_len ? intern->file_name : "");
+                       zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", ZSTR_VAL(intern->file_name));
                }
                intern->file_name = NULL; /* until here it is not a copy */
                intern->u.file.open_mode = NULL;
@@ -317,13 +315,14 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu
        }
        */
 
-       if (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
-               intern->file_name_len--;
+       if (ZSTR_LEN(intern->file_name) > 1 && IS_SLASH_AT(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name)-1)) {
+               intern->file_name = zend_string_init(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name)-1, 0);
+       } else {
+               intern->file_name = zend_string_copy(intern->file_name);
        }
 
-       intern->orig_path = estrndup(intern->u.file.stream->orig_path, strlen(intern->u.file.stream->orig_path));
+       intern->orig_path = zend_string_init(intern->u.file.stream->orig_path, strlen(intern->u.file.stream->orig_path), 0);
 
-       intern->file_name = estrndup(intern->file_name, intern->file_name_len);
        intern->u.file.open_mode = estrndup(intern->u.file.open_mode, intern->u.file.open_mode_len);
 
        /* avoid reference counting in debug mode, thus do it manually */
@@ -363,13 +362,11 @@ static zend_object *spl_filesystem_object_clone(zend_object *old_object)
 
        switch (source->type) {
                case SPL_FS_INFO:
-                       intern->_path_len = source->_path_len;
-                       intern->_path = estrndup(source->_path, source->_path_len);
-                       intern->file_name_len = source->file_name_len;
-                       intern->file_name = estrndup(source->file_name, intern->file_name_len);
+                       intern->path = zend_string_copy(source->path);
+                       intern->file_name = zend_string_copy(source->file_name);
                        break;
                case SPL_FS_DIR:
-                       spl_filesystem_dir_open(intern, source->_path);
+                       spl_filesystem_dir_open(intern, source->path);
                        /* read until we hit the position in which we were before */
                        skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS);
                        for(index = 0; index < source->u.dir.index; ++index) {
@@ -398,58 +395,43 @@ static zend_object *spl_filesystem_object_clone(zend_object *old_object)
 }
 /* }}} */
 
-void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, size_t len, size_t use_copy) /* {{{ */
+static void spl_filesystem_info_set_filename(spl_filesystem_object *intern, zend_string *path) /* {{{ */
 {
-       char *p1, *p2;
+       size_t path_len;
 
        if (intern->file_name) {
-               efree(intern->file_name);
-       }
-
-       intern->file_name = use_copy ? estrndup(path, len) : path;
-       intern->file_name_len = len;
-
-       while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
-               intern->file_name[intern->file_name_len-1] = 0;
-               intern->file_name_len--;
+               zend_string_release(intern->file_name);
        }
 
-       p1 = strrchr(intern->file_name, '/');
-#ifdef PHP_WIN32
-       p2 = strrchr(intern->file_name, '\\');
-#else
-       p2 = 0;
-#endif
-       if (p1 || p2) {
-               intern->_path_len = ((p1 > p2 ? p1 : p2) - intern->file_name);
+       path_len = ZSTR_LEN(path);
+       if (path_len > 1 && IS_SLASH_AT(ZSTR_VAL(path), path_len-1)) {
+               path_len--;
+               intern->file_name = zend_string_init(ZSTR_VAL(path), path_len, 0);
        } else {
-               intern->_path_len = 0;
+               intern->file_name = zend_string_copy(path);
+       }
+       while (path_len > 1 && !IS_SLASH_AT(ZSTR_VAL(path), path_len-1)) {
+               path_len--;
+       }
+       if (path_len) {
+               path_len--;
        }
 
-       if (intern->_path) {
-               efree(intern->_path);
+       if (intern->path) {
+               zend_string_release(intern->path);
        }
-       intern->_path = estrndup(path, intern->_path_len);
+       intern->path = zend_string_init(ZSTR_VAL(path), path_len, 0);
 } /* }}} */
 
-static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, size_t file_path_len, int use_copy, zend_class_entry *ce, zval *return_value) /* {{{ */
+static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, zend_string *file_path, zend_class_entry *ce, zval *return_value) /* {{{ */
 {
        spl_filesystem_object *intern;
        zval arg1;
        zend_error_handling error_handling;
 
-       if (!file_path || !file_path_len) {
+       if (!file_path || !ZSTR_LEN(file_path)) {
 #ifdef PHP_WIN32
                zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot create SplFileInfo for empty path");
-               if (file_path && !use_copy) {
-                       efree(file_path);
-               }
-#else
-               if (file_path && !use_copy) {
-                       efree(file_path);
-               }
-               file_path_len = 1;
-               file_path = "/";
 #endif
                return NULL;
        }
@@ -462,11 +444,11 @@ static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_o
        RETVAL_OBJ(&intern->std);
 
        if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
-               ZVAL_STRINGL(&arg1, file_path, file_path_len);
+               ZVAL_STR_COPY(&arg1, file_path);
                zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
                zval_ptr_dtor(&arg1);
        } else {
-               spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy);
+               spl_filesystem_info_set_filename(intern, file_path);
        }
 
        zend_restore_error_handling(&error_handling);
@@ -503,14 +485,20 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp
                        }
 
                        if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
-                               ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
+                               ZVAL_STR_COPY(&arg1, source->file_name);
                                zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
                                zval_ptr_dtor(&arg1);
                        } else {
-                               intern->file_name = estrndup(source->file_name, source->file_name_len);
-                               intern->file_name_len = source->file_name_len;
-                               intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
-                               intern->_path = estrndup(intern->_path, intern->_path_len);
+                               char *path;
+                               size_t path_len;
+
+                               intern->file_name = zend_string_copy(source->file_name);
+                               path = spl_filesystem_object_get_path(source, &path_len);
+                               if (source->path && ZSTR_VAL(source->path) == path) {
+                                       intern->path = zend_string_copy(source->path);
+                               } else {
+                                       intern->path = zend_string_init(path, path_len, 0);
+                               }
                        }
                        break;
                case SPL_FS_FILE:
@@ -535,16 +523,22 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, sp
                        }
 
                        if (ce->constructor->common.scope != spl_ce_SplFileObject) {
-                               ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
+                               ZVAL_STR_COPY(&arg1, source->file_name);
                                ZVAL_STRINGL(&arg2, open_mode, open_mode_len);
                                zend_call_method_with_2_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1, &arg2);
                                zval_ptr_dtor(&arg1);
                                zval_ptr_dtor(&arg2);
                        } else {
+                               char *path;
+                               size_t path_len;
+
                                intern->file_name = source->file_name;
-                               intern->file_name_len = source->file_name_len;
-                               intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
-                               intern->_path = estrndup(intern->_path, intern->_path_len);
+                               path = spl_filesystem_object_get_path(source, &path_len);
+                               if (source->path && ZSTR_VAL(source->path) == path) {
+                                       intern->path = zend_string_copy(source->path);
+                               } else {
+                                       intern->path = zend_string_init(path, path_len, 0);
+                               }
 
                                intern->u.file.open_mode = open_mode;
                                intern->u.file.open_mode_len = open_mode_len;
@@ -574,20 +568,17 @@ static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */
 }
 /* }}} */
 
-static char *spl_filesystem_object_get_pathname(spl_filesystem_object *intern, size_t *len) { /* {{{ */
+static zend_string *spl_filesystem_object_get_pathname(spl_filesystem_object *intern) { /* {{{ */
        switch (intern->type) {
                case SPL_FS_INFO:
                case SPL_FS_FILE:
-                       *len = intern->file_name_len;
                        return intern->file_name;
                case SPL_FS_DIR:
                        if (intern->u.dir.entry.d_name[0]) {
                                spl_filesystem_object_get_file_name(intern);
-                               *len = intern->file_name_len;
                                return intern->file_name;
                        }
        }
-       *len = 0;
        return NULL;
 }
 /* }}} */
@@ -598,8 +589,7 @@ static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *objec
        zval tmp;
        HashTable *rv;
        zend_string *pnstr;
-       char *path;
-       size_t  path_len;
+       zend_string *path;
        char stmp[2];
 
        if (!intern->std.properties) {
@@ -609,19 +599,25 @@ static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *objec
        rv = zend_array_dup(intern->std.properties);
 
        pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1);
-       path = spl_filesystem_object_get_pathname(intern, &path_len);
-       ZVAL_STRINGL(&tmp, path ? path : "", path_len);
+       path = spl_filesystem_object_get_pathname(intern);
+       if (path) {
+               ZVAL_STR_COPY(&tmp, path);
+       } else {
+               ZVAL_EMPTY_STRING(&tmp);
+       }
        zend_symtable_update(rv, pnstr, &tmp);
        zend_string_release_ex(pnstr, 0);
 
        if (intern->file_name) {
+               size_t path_len;
+
                pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1);
                spl_filesystem_object_get_path(intern, &path_len);
 
-               if (path_len && path_len < intern->file_name_len) {
-                       ZVAL_STRINGL(&tmp, intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
+               if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
+                       ZVAL_STRINGL(&tmp, ZSTR_VAL(intern->file_name) + path_len + 1, ZSTR_LEN(intern->file_name) - (path_len + 1));
                } else {
-                       ZVAL_STRINGL(&tmp, intern->file_name, intern->file_name_len);
+                       ZVAL_STR_COPY(&tmp, intern->file_name);
                }
                zend_symtable_update(rv, pnstr, &tmp);
                zend_string_release_ex(pnstr, 0);
@@ -630,7 +626,7 @@ static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *objec
 #ifdef HAVE_GLOB
                pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1);
                if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
-                       ZVAL_STRINGL(&tmp, intern->_path, intern->_path_len);
+                       ZVAL_STR_COPY(&tmp, intern->path);
                } else {
                        ZVAL_FALSE(&tmp);
                }
@@ -639,7 +635,7 @@ static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *objec
 #endif
                pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1);
                if (intern->u.dir.sub_path) {
-                       ZVAL_STRINGL(&tmp, intern->u.dir.sub_path, intern->u.dir.sub_path_len);
+                       ZVAL_STR_COPY(&tmp, intern->u.dir.sub_path);
                } else {
                        ZVAL_EMPTY_STRING(&tmp);
                }
@@ -690,18 +686,17 @@ zend_function *spl_filesystem_object_get_method_check(zend_object **object, zend
 void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long ctor_flags) /* {{{ */
 {
        spl_filesystem_object *intern;
-       char *path;
+       zend_string *path;
        int parsed;
-       size_t len;
        zend_long flags;
        zend_error_handling error_handling;
 
        if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
                flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
-               parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &path, &len, &flags);
+               parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &path, &flags);
        } else {
                flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
-               parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p", &path, &len);
+               parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "P", &path);
        }
        if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_SKIPDOTS)) {
                flags |= SPL_FILE_DIR_SKIPDOTS;
@@ -713,13 +708,13 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long cto
                RETURN_THROWS();
        }
 
-       if (len == 0) {
+       if (ZSTR_LEN(path) == 0) {
                zend_argument_value_error(1, "cannot be empty");
                RETURN_THROWS();
        }
 
        intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
-       if (intern->_path) {
+       if (intern->path) {
                /* object is already initialized */
                zend_throw_error(NULL, "Directory object is already initialized");
                RETURN_THROWS();
@@ -728,10 +723,10 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long cto
 
        zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
 #ifdef HAVE_GLOB
-       if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && strstr(path, "glob://") != path) {
-               spprintf(&path, 0, "glob://%s", path);
+       if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && memcmp(ZSTR_VAL(path), "glob://", sizeof("glob://")-1) != 0) {
+               path = zend_strpprintf(0, "glob://%s", ZSTR_VAL(path));
                spl_filesystem_dir_open(intern, path);
-               efree(path);
+               zend_string_release(path);
        } else
 #endif
        {
@@ -811,7 +806,7 @@ PHP_METHOD(DirectoryIterator, next)
                spl_filesystem_dir_read(intern);
        } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
        if (intern->file_name) {
-               efree(intern->file_name);
+               zend_string_release(intern->file_name);
                intern->file_name = NULL;
        }
 }
@@ -896,10 +891,10 @@ PHP_METHOD(SplFileInfo, getFilename)
 
        spl_filesystem_object_get_path(intern, &path_len);
 
-       if (path_len && path_len < intern->file_name_len) {
-               RETURN_STRINGL(intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
+       if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
+               RETURN_STRINGL(ZSTR_VAL(intern->file_name) + path_len + 1, ZSTR_LEN(intern->file_name) - (path_len + 1));
        } else {
-               RETURN_STRINGL(intern->file_name, intern->file_name_len);
+               RETURN_STR_COPY(intern->file_name);
        }
 }
 /* }}} */
@@ -939,12 +934,12 @@ PHP_METHOD(SplFileInfo, getExtension)
 
        spl_filesystem_object_get_path(intern, &path_len);
 
-       if (path_len && path_len < intern->file_name_len) {
-               fname = intern->file_name + path_len + 1;
-               flen = intern->file_name_len - (path_len + 1);
+       if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
+               fname = ZSTR_VAL(intern->file_name) + path_len + 1;
+               flen = ZSTR_LEN(intern->file_name) - (path_len + 1);
        } else {
-               fname = intern->file_name;
-               flen = intern->file_name_len;
+               fname = ZSTR_VAL(intern->file_name);
+               flen = ZSTR_LEN(intern->file_name);
        }
 
        ret = php_basename(fname, flen, NULL, 0);
@@ -1007,12 +1002,12 @@ PHP_METHOD(SplFileInfo, getBasename)
 
        spl_filesystem_object_get_path(intern, &path_len);
 
-       if (path_len && path_len < intern->file_name_len) {
-               fname = intern->file_name + path_len + 1;
-               flen = intern->file_name_len - (path_len + 1);
+       if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
+               fname = ZSTR_VAL(intern->file_name) + path_len + 1;
+               flen = ZSTR_LEN(intern->file_name) - (path_len + 1);
        } else {
-               fname = intern->file_name;
-               flen = intern->file_name_len;
+               fname = ZSTR_VAL(intern->file_name);
+               flen = ZSTR_LEN(intern->file_name);
        }
 
        RETURN_STR(php_basename(fname, flen, suffix, slen));
@@ -1041,15 +1036,14 @@ PHP_METHOD(DirectoryIterator, getBasename)
 PHP_METHOD(SplFileInfo, getPathname)
 {
        spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
-       char *path;
-       size_t path_len;
+       zend_string *path;
 
        if (zend_parse_parameters_none() == FAILURE) {
                RETURN_THROWS();
        }
-       path = spl_filesystem_object_get_pathname(intern, &path_len);
-       if (path != NULL) {
-               RETURN_STRINGL(path, path_len);
+       path = spl_filesystem_object_get_pathname(intern);
+       if (path) {
+               RETURN_STR_COPY(path);
        } else {
                RETURN_EMPTY_STRING();
        }
@@ -1071,7 +1065,7 @@ PHP_METHOD(FilesystemIterator, key)
                if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
                        RETURN_THROWS();
                }
-               RETURN_STRINGL(intern->file_name, intern->file_name_len);
+               RETURN_STR_COPY(intern->file_name);
        }
 }
 /* }}} */
@@ -1089,7 +1083,7 @@ PHP_METHOD(FilesystemIterator, current)
                if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
                        RETURN_THROWS();
                }
-               RETURN_STRINGL(intern->file_name, intern->file_name_len);
+               RETURN_STR_COPY(intern->file_name);
        } else if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
                if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
                        RETURN_THROWS();
@@ -1121,16 +1115,15 @@ PHP_METHOD(DirectoryIterator, isDot)
 PHP_METHOD(SplFileInfo, __construct)
 {
        spl_filesystem_object *intern;
-       char *path;
-       size_t len;
+       zend_string *path;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &path, &len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &path) == FAILURE) {
                RETURN_THROWS();
        }
 
        intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
 
-       spl_filesystem_info_set_filename(intern, path, len, 1);
+       spl_filesystem_info_set_filename(intern, path);
 
        /* intern->type = SPL_FS_INFO; already set */
 }
@@ -1149,7 +1142,7 @@ PHP_METHOD(SplFileInfo, func_name) \
                RETURN_THROWS(); \
        } \
        zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);\
-       php_stat(intern->file_name, intern->file_name_len, func_num, return_value); \
+       php_stat(intern->file_name, func_num, return_value); \
        zend_restore_error_handling(&error_handling); \
 }
 /* }}} */
@@ -1239,23 +1232,23 @@ PHP_METHOD(SplFileInfo, getLinkTarget)
                zend_value_error("Filename cannot be empty");
                RETURN_THROWS();
        }
-       if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) {
+       if (!IS_ABSOLUTE_PATH(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name))) {
                char expanded_path[MAXPATHLEN];
-               if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND )) {
+               if (!expand_filepath_with_mode(ZSTR_VAL(intern->file_name), expanded_path, NULL, 0, CWD_EXPAND )) {
                        zend_restore_error_handling(&error_handling);
                        php_error_docref(NULL, E_WARNING, "No such file or directory");
                        RETURN_FALSE;
                }
                ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1);
        } else {
-               ret = php_sys_readlink(intern->file_name, buff,  MAXPATHLEN-1);
+               ret = php_sys_readlink(ZSTR_VAL(intern->file_name), buff,  MAXPATHLEN-1);
        }
 #else
        ret = -1; /* always fail if not implemented */
 #endif
 
        if (ret == -1) {
-               zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", intern->file_name, strerror(errno));
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", ZSTR_VAL(intern->file_name), strerror(errno));
                RETVAL_FALSE;
        } else {
                /* Append NULL to the end of the string */
@@ -1290,9 +1283,9 @@ PHP_METHOD(SplFileInfo, getRealPath)
        }
 
        if (intern->orig_path) {
-               filename = intern->orig_path;
+               filename = ZSTR_VAL(intern->orig_path);
        } else {
-               filename = intern->file_name;
+               filename = intern->file_name ? ZSTR_VAL(intern->file_name) : NULL;
        }
 
 
@@ -1367,19 +1360,18 @@ PHP_METHOD(SplFileInfo, getPathInfo)
 {
        spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
        zend_class_entry *ce = intern->info_class;
-       size_t path_len;
-       char *path;
+       zend_string *path;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C!", &ce) == FAILURE) {
                RETURN_THROWS();
        }
 
-       path = spl_filesystem_object_get_pathname(intern, &path_len);
-       if (path) {
-               char *dpath = estrndup(path, path_len);
-               path_len = php_dirname(dpath, path_len);
-               spl_filesystem_object_create_info(intern, dpath, path_len, 1, ce, return_value);
-               efree(dpath);
+       path = spl_filesystem_object_get_pathname(intern);
+       if (path && ZSTR_LEN(path)) {
+               zend_string *dpath = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path), 0);
+               ZSTR_LEN(dpath) = php_dirname(ZSTR_VAL(dpath), ZSTR_LEN(path));
+               spl_filesystem_object_create_info(intern, dpath, ce, return_value);
+               zend_string_release(dpath);
        }
 }
 /* }}} */
@@ -1470,12 +1462,12 @@ PHP_METHOD(RecursiveDirectoryIterator, hasChildren)
                        RETURN_THROWS();
                }
                if (!allow_links && !(intern->flags & SPL_FILE_DIR_FOLLOW_SYMLINKS)) {
-                       php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value);
+                       php_stat(intern->file_name, FS_IS_LINK, return_value);
                        if (zend_is_true(return_value)) {
                                RETURN_FALSE;
                        }
                }
-               php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value);
+               php_stat(intern->file_name, FS_IS_DIR, return_value);
     }
 }
 /* }}} */
@@ -1497,17 +1489,16 @@ PHP_METHOD(RecursiveDirectoryIterator, getChildren)
        }
 
        ZVAL_LONG(&zflags, intern->flags);
-       ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len);
+       ZVAL_STR_COPY(&zpath, intern->file_name);
        spl_instantiate_arg_ex2(Z_OBJCE_P(ZEND_THIS), return_value, &zpath, &zflags);
        zval_ptr_dtor(&zpath);
 
        subdir = Z_SPLFILESYSTEM_P(return_value);
        if (subdir) {
-               if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
-                       subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name);
+               if (intern->u.dir.sub_path && ZSTR_LEN(intern->u.dir.sub_path)) {
+                       subdir->u.dir.sub_path = zend_strpprintf(0, "%s%c%s", ZSTR_VAL(intern->u.dir.sub_path), slash, intern->u.dir.entry.d_name);
                } else {
-                       subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name);
-                       subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
+                       subdir->u.dir.sub_path = zend_string_init(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), 0);
                }
                subdir->info_class = intern->info_class;
                subdir->file_class = intern->file_class;
@@ -1526,7 +1517,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getSubPath)
        }
 
        if (intern->u.dir.sub_path) {
-               RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len);
+               RETURN_STR_COPY(intern->u.dir.sub_path);
        } else {
                RETURN_EMPTY_STRING();
        }
@@ -1544,7 +1535,7 @@ PHP_METHOD(RecursiveDirectoryIterator, getSubPathname)
        }
 
        if (intern->u.dir.sub_path) {
-               RETURN_NEW_STR(strpprintf(0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name));
+               RETURN_NEW_STR(strpprintf(0, "%s%c%s", ZSTR_VAL(intern->u.dir.sub_path), slash, intern->u.dir.entry.d_name));
        } else {
                RETURN_STRING(intern->u.dir.entry.d_name);
        }
@@ -1672,7 +1663,7 @@ static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter)
        object->u.dir.index++;
        spl_filesystem_dir_read(object);
        if (object->file_name) {
-               efree(object->file_name);
+               zend_string_release(object->file_name);
                object->file_name = NULL;
        }
 }
@@ -1711,7 +1702,7 @@ static zval *spl_filesystem_tree_it_current_data(zend_object_iterator *iter)
                        if (spl_filesystem_object_get_file_name(object) != SUCCESS) {
                                return NULL;
                        }
-                       ZVAL_STRINGL(&iterator->current, object->file_name, object->file_name_len);
+                       ZVAL_STR_COPY(&iterator->current, object->file_name);
                }
                return &iterator->current;
        } else if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
@@ -1739,7 +1730,7 @@ static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval
                if (spl_filesystem_object_get_file_name(object) != SUCCESS) {
                        return;
                }
-               ZVAL_STRINGL(key, object->file_name, object->file_name_len);
+               ZVAL_STR_COPY(key, object->file_name);
        }
 }
 /* }}} */
@@ -1755,7 +1746,7 @@ static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter)
                spl_filesystem_dir_read(object);
        } while (spl_filesystem_is_dot(object->u.dir.entry.d_name));
        if (object->file_name) {
-               efree(object->file_name);
+               zend_string_release(object->file_name);
                object->file_name = NULL;
        }
        if (!Z_ISUNDEF(iterator->current)) {
@@ -1831,7 +1822,7 @@ static int spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int
                switch (intern->type) {
                case SPL_FS_INFO:
                case SPL_FS_FILE:
-                       ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len);
+                       ZVAL_STR_COPY(writeobj, intern->file_name);
                        return SUCCESS;
                case SPL_FS_DIR:
                        ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
@@ -1856,7 +1847,7 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /
 
        if (php_stream_eof(intern->u.file.stream)) {
                if (!silent) {
-                       zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
+                       zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", ZSTR_VAL(intern->file_name));
                }
                return FAILURE;
        }
@@ -1926,7 +1917,7 @@ static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_obje
        if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
                if (php_stream_eof(intern->u.file.stream)) {
                        if (!silent) {
-                               zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
+                               zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", ZSTR_VAL(intern->file_name));
                        }
                        return FAILURE;
                }
@@ -2011,7 +2002,7 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i
                return;
        }
        if (-1 == php_stream_rewind(intern->u.file.stream)) {
-               zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", intern->file_name);
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", ZSTR_VAL(intern->file_name));
        } else {
                spl_filesystem_file_free_line(intern);
                intern->u.file.current_line_num = 0;
@@ -2026,16 +2017,14 @@ PHP_METHOD(SplFileObject, __construct)
 {
        spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
        bool use_include_path = 0;
-       char *p1, *p2;
-       char *tmp_path;
-       size_t   tmp_path_len;
+       size_t path_len;
        zend_error_handling error_handling;
 
        intern->u.file.open_mode = NULL;
        intern->u.file.open_mode_len = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|sbr!",
-                       &intern->file_name, &intern->file_name_len,
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|sbr!",
+                       &intern->file_name,
                        &intern->u.file.open_mode, &intern->u.file.open_mode_len,
                        &use_include_path, &intern->u.file.zcontext) == FAILURE) {
                intern->u.file.open_mode = NULL;
@@ -2051,29 +2040,21 @@ PHP_METHOD(SplFileObject, __construct)
        zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
 
        if (spl_filesystem_file_open(intern, use_include_path, 0) == SUCCESS) {
-               tmp_path_len = strlen(intern->u.file.stream->orig_path);
+               path_len = strlen(intern->u.file.stream->orig_path);
 
-               if (tmp_path_len > 1 && IS_SLASH_AT(intern->u.file.stream->orig_path, tmp_path_len-1)) {
-                       tmp_path_len--;
+               if (path_len > 1 && IS_SLASH_AT(intern->u.file.stream->orig_path, path_len-1)) {
+                       path_len--;
                }
 
-               tmp_path = estrndup(intern->u.file.stream->orig_path, tmp_path_len);
-
-               p1 = strrchr(tmp_path, '/');
-#ifdef PHP_WIN32
-               p2 = strrchr(tmp_path, '\\');
-#else
-               p2 = 0;
-#endif
-               if (p1 || p2) {
-                       intern->_path_len = ((p1 > p2 ? p1 : p2) - tmp_path);
-               } else {
-                       intern->_path_len = 0;
+               while (path_len > 1 && !IS_SLASH_AT(intern->u.file.stream->orig_path, path_len-1)) {
+                       path_len--;
                }
 
-               efree(tmp_path);
+               if (path_len) {
+                       path_len--;
+               }
 
-               intern->_path = estrndup(intern->u.file.stream->orig_path, intern->_path_len);
+               intern->path = zend_string_init(intern->u.file.stream->orig_path, path_len, 0);
        }
 
        zend_restore_error_handling(&error_handling);
@@ -2083,8 +2064,8 @@ PHP_METHOD(SplFileObject, __construct)
 /* {{{ Construct a new temp file object */
 PHP_METHOD(SplTempFileObject, __construct)
 {
+       zend_string *file_name;
        zend_long max_memory = PHP_STREAM_MAX_MEM;
-       char tmp_fname[48];
        spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
        zend_error_handling error_handling;
 
@@ -2093,23 +2074,21 @@ PHP_METHOD(SplTempFileObject, __construct)
        }
 
        if (max_memory < 0) {
-               intern->file_name = "php://memory";
-               intern->file_name_len = 12;
+               file_name = zend_string_init("php://memory", sizeof("php://memory")-1, 0);
        } else if (ZEND_NUM_ARGS()) {
-               intern->file_name_len = slprintf(tmp_fname, sizeof(tmp_fname), "php://temp/maxmemory:" ZEND_LONG_FMT, max_memory);
-               intern->file_name = tmp_fname;
+               file_name = zend_strpprintf(0, "php://temp/maxmemory:" ZEND_LONG_FMT, max_memory);
        } else {
-               intern->file_name = "php://temp";
-               intern->file_name_len = 10;
+               file_name = zend_string_init("php://temp", sizeof("php://temp")-1, 0);
        }
+       intern->file_name = file_name;
        intern->u.file.open_mode = "wb";
        intern->u.file.open_mode_len = 1;
 
        zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
        if (spl_filesystem_file_open(intern, 0, 0) == SUCCESS) {
-               intern->_path_len = 0;
-               intern->_path = estrndup("", 0);
+               intern->path = ZSTR_EMPTY_ALLOC();
        }
+       zend_string_release(file_name);
        zend_restore_error_handling(&error_handling);
 } /* }}} */
 
@@ -2690,7 +2669,7 @@ PHP_METHOD(SplFileObject, ftruncate)
        CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
 
        if (!php_stream_truncate_supported(intern->u.file.stream)) {
-               zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", intern->file_name);
+               zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", ZSTR_VAL(intern->file_name));
                RETURN_THROWS();
        }
 
index e3deb81aebff3a4f7f6a764c2f84ed33572b01fd..9c93aa2608784c6d3600cf5372fd2539e1c00a7d 100644 (file)
@@ -58,11 +58,9 @@ typedef struct {
 struct _spl_filesystem_object {
        void               *oth;
        const spl_other_handler  *oth_handler;
-       char               *_path;
-       size_t             _path_len;
-       char               *orig_path;
-       char               *file_name;
-       size_t             file_name_len;
+       zend_string        *path;
+       zend_string        *orig_path;
+       zend_string        *file_name;
        SPL_FS_OBJ_TYPE    type;
        zend_long               flags;
        zend_class_entry   *file_class;
@@ -71,8 +69,7 @@ struct _spl_filesystem_object {
                struct {
                        php_stream         *dirp;
                        php_stream_dirent  entry;
-                       char               *sub_path;
-                       size_t             sub_path_len;
+                       zend_string        *sub_path;
                        int                index;
                        int                is_recursive;
                        zend_function      *func_rewind;
index 5971ffd2abad68c33e4632260e7a9ef380d1c61d..6df50d42e10882896a5b8481a8c1c9d893891b45 100644 (file)
@@ -79,7 +79,7 @@ typedef struct _php_basic_globals {
        time_t page_mtime;
 
        /* filestat.c && main/streams/streams.c */
-       char *CurrentStatFile, *CurrentLStatFile;
+       zend_string *CurrentStatFile, *CurrentLStatFile;
        php_stream_statbuf ssb, lssb;
 
        /* mt_rand.c */
index c75db7e45aaff6936b65b8d4388f7516cb9012ce..7d3af076977c38702f41bf7fb0fd031d6c7542c2 100644 (file)
@@ -317,12 +317,12 @@ PHP_FUNCTION(chdir)
                RETURN_FALSE;
        }
 
-       if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentStatFile), strlen(BG(CurrentStatFile)))) {
-               efree(BG(CurrentStatFile));
+       if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(ZSTR_VAL(BG(CurrentStatFile)), ZSTR_LEN(BG(CurrentStatFile)))) {
+               zend_string_release(BG(CurrentStatFile));
                BG(CurrentStatFile) = NULL;
        }
-       if (BG(CurrentLStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentLStatFile), strlen(BG(CurrentLStatFile)))) {
-               efree(BG(CurrentLStatFile));
+       if (BG(CurrentLStatFile) && !IS_ABSOLUTE_PATH(ZSTR_VAL(BG(CurrentLStatFile)), ZSTR_LEN(BG(CurrentLStatFile)))) {
+               zend_string_release(BG(CurrentLStatFile));
                BG(CurrentLStatFile) = NULL;
        }
 
index f2859f5477dc4aaa22d0ceae4fd7dc30cd61a7ea..ff29bf1b1c0a03076eab2e2f9efd99dc6fb2cea0 100644 (file)
@@ -1643,7 +1643,7 @@ PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_flg, php
                return FAILURE;
        }
 
-       switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET | PHP_STREAM_URL_STAT_NOCACHE, &dest_s, ctx)) {
+       switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET, &dest_s, ctx)) {
                case -1:
                        /* non-statable stream */
                        goto safe_to_copy;
index 0f39116676060ae82850d26f2c3edd8ba2d80313..0b488df4b26e945899b943699ec079db5ee96211 100644 (file)
@@ -88,11 +88,11 @@ PHP_RINIT_FUNCTION(filestat) /* {{{ */
 PHP_RSHUTDOWN_FUNCTION(filestat) /* {{{ */
 {
        if (BG(CurrentStatFile)) {
-               efree (BG(CurrentStatFile));
+               zend_string_release(BG(CurrentStatFile));
                BG(CurrentStatFile) = NULL;
        }
        if (BG(CurrentLStatFile)) {
-               efree (BG(CurrentLStatFile));
+               zend_string_release(BG(CurrentLStatFile));
                BG(CurrentLStatFile) = NULL;
        }
        return SUCCESS;
@@ -680,11 +680,11 @@ PHPAPI void php_clear_stat_cache(bool clear_realpath_cache, const char *filename
         * as it may contain outdated data (e.g. "nlink" for a directory when deleting a file
         * in this directory, as shown by lstat_stat_variation9.phpt) */
        if (BG(CurrentStatFile)) {
-               efree(BG(CurrentStatFile));
+               zend_string_release(BG(CurrentStatFile));
                BG(CurrentStatFile) = NULL;
        }
        if (BG(CurrentLStatFile)) {
-               efree(BG(CurrentLStatFile));
+               zend_string_release(BG(CurrentLStatFile));
                BG(CurrentLStatFile) = NULL;
        }
        if (clear_realpath_cache) {
@@ -720,26 +720,27 @@ PHP_FUNCTION(clearstatcache)
 #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
 
 /* {{{ php_stat */
-PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value)
+PHPAPI void php_stat(zend_string *filename, int type, zval *return_value)
 {
        zend_stat_t *stat_sb;
        php_stream_statbuf ssb;
        int flags = 0, rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
-       const char *local;
-       php_stream_wrapper *wrapper;
+       const char *local = NULL;
+       php_stream_wrapper *wrapper = NULL;
 
-       if (!filename_length || CHECK_NULL_PATH(filename, filename_length)) {
-               if (filename_length && !IS_EXISTS_CHECK(type)) {
-                       php_error_docref(NULL, E_WARNING, "Filename contains null byte");
+       if (IS_ACCESS_CHECK(type)) {
+               if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) {
+                       if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) {
+                               php_error_docref(NULL, E_WARNING, "Filename contains null byte");
+                       }
+                       RETURN_FALSE;
                }
-               RETURN_FALSE;
-       }
 
-       if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0)) == &php_plain_files_wrapper && php_check_open_basedir(local)) {
-               RETURN_FALSE;
-       }
+               if ((wrapper = php_stream_locate_url_wrapper(ZSTR_VAL(filename), &local, 0)) == &php_plain_files_wrapper
+                && php_check_open_basedir(local)) {
+                       RETURN_FALSE;
+               }
 
-       if (IS_ACCESS_CHECK(type)) {
                if (wrapper == &php_plain_files_wrapper) {
 
                        switch (type) {
@@ -774,13 +775,63 @@ PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zva
                flags |= PHP_STREAM_URL_STAT_QUIET;
        }
 
-       if (php_stream_stat_path_ex((char *)filename, flags, &ssb, NULL)) {
-               /* Error Occurred */
-               if (!IS_EXISTS_CHECK(type)) {
-                       php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
+       do {
+               /* Try to hit the cache first */
+               if (flags & PHP_STREAM_URL_STAT_LINK) {
+                       if (filename == BG(CurrentLStatFile)
+                        || (BG(CurrentLStatFile)
+                         && zend_string_equal_content(filename, BG(CurrentLStatFile)))) {
+                               memcpy(&ssb, &BG(lssb), sizeof(php_stream_statbuf));
+                               break;
+                       }
+               } else {
+                       if (filename == BG(CurrentStatFile)
+                        || (BG(CurrentStatFile)
+                         && zend_string_equal_content(filename, BG(CurrentStatFile)))) {
+                               memcpy(&ssb, &BG(ssb), sizeof(php_stream_statbuf));
+                               break;
+                       }
                }
-               RETURN_FALSE;
-       }
+
+               if (!wrapper) {
+                       if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) {
+                               if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) {
+                                       php_error_docref(NULL, E_WARNING, "Filename contains null byte");
+                               }
+                               RETURN_FALSE;
+                       }
+
+                       if ((wrapper = php_stream_locate_url_wrapper(ZSTR_VAL(filename), &local, 0)) == &php_plain_files_wrapper
+                        && php_check_open_basedir(local)) {
+                               RETURN_FALSE;
+                       }
+               }
+
+               if (!wrapper
+                || !wrapper->wops->url_stat
+                || wrapper->wops->url_stat(wrapper, local, flags | PHP_STREAM_URL_STAT_IGNORE_OPEN_BASEDIR, &ssb, NULL)) {
+                       /* Error Occurred */
+                       if (!IS_EXISTS_CHECK(type)) {
+                               php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", ZSTR_VAL(filename));
+                       }
+                       RETURN_FALSE;
+               }
+
+               /* Drop into cache */
+               if (flags & PHP_STREAM_URL_STAT_LINK) {
+                       if (BG(CurrentLStatFile)) {
+                               zend_string_release(BG(CurrentLStatFile));
+                       }
+                       BG(CurrentLStatFile) = zend_string_copy(filename);
+                       memcpy(&BG(lssb), &ssb, sizeof(php_stream_statbuf));
+               } else {
+                       if (BG(CurrentStatFile)) {
+                               zend_string_release(BG(CurrentStatFile));
+                       }
+                       BG(CurrentStatFile) = zend_string_copy(filename);
+                       memcpy(&BG(ssb), &ssb, sizeof(php_stream_statbuf));
+               }
+       } while (0);
 
        stat_sb = &ssb.sb;
 
@@ -936,14 +987,13 @@ PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zva
 /* {{{ FileFunction(name, funcnum) */
 #define FileFunction(name, funcnum) \
 ZEND_NAMED_FUNCTION(name) { \
-       char *filename; \
-       size_t filename_len; \
+       zend_string *filename; \
        \
        ZEND_PARSE_PARAMETERS_START(1, 1) \
-               Z_PARAM_STRING(filename, filename_len) \
+               Z_PARAM_STR(filename) \
        ZEND_PARSE_PARAMETERS_END(); \
        \
-       php_stat(filename, filename_len, funcnum, return_value); \
+       php_stat(filename, funcnum, return_value); \
 }
 /* }}} */
 
index 4f76fc39c34be4b96c707924c4fddaaf93bc936a..ab4e32729d4c445d81f3211f1bbb173f3e4fa238 100644 (file)
@@ -41,7 +41,7 @@ PHP_RSHUTDOWN_FUNCTION(filestat);
 typedef size_t php_stat_len;
 
 PHPAPI void php_clear_stat_cache(bool clear_realpath_cache, const char *filename, size_t filename_len);
-PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value);
+PHPAPI void php_stat(zend_string *filename, int type, zval *return_value);
 
 /* Switches for various filestat functions: */
 #define FS_PERMS    0
index a3b266bba8489ba5148da040588822d77874944b..e62f9fc8f9f4120b37597f8adae0f7be8f9c0c1b 100644 (file)
@@ -280,8 +280,7 @@ static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t fil
 {
        struct zip_source *zs;
        char resolved_path[MAXPATHLEN];
-       zval exists_flag;
-
+       php_stream_statbuf ssb;
 
        if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
                return -1;
@@ -292,8 +291,7 @@ static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t fil
                return -1;
        }
 
-       php_stat(resolved_path, strlen(resolved_path), FS_EXISTS, &exists_flag);
-       if (Z_TYPE(exists_flag) == IS_FALSE) {
+       if (php_stream_stat_path_ex(resolved_path, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL)) {
                php_error_docref(NULL, E_WARNING, "No such file or directory");
                return -1;
        }
index 60be0a79eb49bec8ee50b3ed126f94508035703f..f7196b84376226cd8b490bbb88549a902955648d 100644 (file)
@@ -391,7 +391,7 @@ END_EXTERN_C()
 /* Flags for url_stat method in wrapper ops */
 #define PHP_STREAM_URL_STAT_LINK       1
 #define PHP_STREAM_URL_STAT_QUIET      2
-#define PHP_STREAM_URL_STAT_NOCACHE    4
+#define PHP_STREAM_URL_STAT_IGNORE_OPEN_BASEDIR        4
 
 /* change the blocking mode of stream: value == 1 => blocking, value == 0 => non-blocking. */
 #define PHP_STREAM_OPTION_BLOCKING     1
index a63c225a0da5541374e5cefd321c7ef8b64fd9fc..58b5b64e0e9c18a5844be27d51a4470e1f4c2463 100644 (file)
@@ -1157,12 +1157,14 @@ static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, co
 
 static int php_plain_files_url_stater(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context)
 {
-       if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) {
-               url += sizeof("file://") - 1;
-       }
+       if (!(flags & PHP_STREAM_URL_STAT_IGNORE_OPEN_BASEDIR)) {
+               if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) {
+                       url += sizeof("file://") - 1;
+               }
 
-       if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1)) {
-               return -1;
+               if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1)) {
+                       return -1;
+               }
        }
 
 #ifdef PHP_WIN32
index e5e90e0f4de52ffc6f10fd901e88b75d09ea9d8c..96d3aeb41e54ac64bfa9033793ac944887ebd1dc 100644 (file)
@@ -1975,47 +1975,12 @@ PHPAPI int _php_stream_stat_path(const char *path, int flags, php_stream_statbuf
 {
        php_stream_wrapper *wrapper = NULL;
        const char *path_to_open = path;
-       int ret;
 
        memset(ssb, 0, sizeof(*ssb));
 
-       if (!(flags & PHP_STREAM_URL_STAT_NOCACHE)) {
-               /* Try to hit the cache first */
-               if (flags & PHP_STREAM_URL_STAT_LINK) {
-                       if (BG(CurrentLStatFile) && strcmp(path, BG(CurrentLStatFile)) == 0) {
-                               memcpy(ssb, &BG(lssb), sizeof(php_stream_statbuf));
-                               return 0;
-                       }
-               } else {
-                       if (BG(CurrentStatFile) && strcmp(path, BG(CurrentStatFile)) == 0) {
-                               memcpy(ssb, &BG(ssb), sizeof(php_stream_statbuf));
-                               return 0;
-                       }
-               }
-       }
-
        wrapper = php_stream_locate_url_wrapper(path, &path_to_open, 0);
        if (wrapper && wrapper->wops->url_stat) {
-               ret = wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context);
-               if (ret == 0) {
-                       if (!(flags & PHP_STREAM_URL_STAT_NOCACHE)) {
-                               /* Drop into cache */
-                               if (flags & PHP_STREAM_URL_STAT_LINK) {
-                                       if (BG(CurrentLStatFile)) {
-                                               efree(BG(CurrentLStatFile));
-                                       }
-                                       BG(CurrentLStatFile) = estrdup(path);
-                                       memcpy(&BG(lssb), ssb, sizeof(php_stream_statbuf));
-                               } else {
-                                       if (BG(CurrentStatFile)) {
-                                               efree(BG(CurrentStatFile));
-                                       }
-                                       BG(CurrentStatFile) = estrdup(path);
-                                       memcpy(&BG(ssb), ssb, sizeof(php_stream_statbuf));
-                               }
-                       }
-               }
-               return ret;
+               return wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context);
        }
        return -1;
 }
index ec78f18db726f7372ac610f1f1aa6525395e6745..097d4bc6c77e08ac32a44b891b4dca3abd322aff 100644 (file)
@@ -175,12 +175,12 @@ void phpdbg_webdata_decompress(char *msg, int len) {
 
        if ((zvp = zend_hash_str_find(ht, ZEND_STRL("cwd"))) && Z_TYPE_P(zvp) == IS_STRING) {
                if (VCWD_CHDIR(Z_STRVAL_P(zvp)) == SUCCESS) {
-                       if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentStatFile), strlen(BG(CurrentStatFile)))) {
-                               efree(BG(CurrentStatFile));
+                       if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(ZSTR_VAL(BG(CurrentStatFile)), ZSTR_LEN(BG(CurrentStatFile)))) {
+                               zend_string_release(BG(CurrentStatFile));
                                BG(CurrentStatFile) = NULL;
                        }
-                       if (BG(CurrentLStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentLStatFile), strlen(BG(CurrentLStatFile)))) {
-                               efree(BG(CurrentLStatFile));
+                       if (BG(CurrentLStatFile) && !IS_ABSOLUTE_PATH(ZSTR_VAL(BG(CurrentLStatFile)), ZSTR_LEN(BG(CurrentLStatFile)))) {
+                               zend_string_release(BG(CurrentLStatFile));
                                BG(CurrentLStatFile) = NULL;
                        }
                }