diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 51e5d70a6e65..c486fd41abfd 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -350,7 +350,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo php_url *resource = NULL; /* pre-readonly check, we need to know if this is a data phar */ - if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, NULL, NULL, 2, 2)) { + if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, NULL, 2, 2)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", no phar archive specified", url_from); return 0; } @@ -476,7 +476,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options php_url *resource = NULL; /* pre-readonly check, we need to know if this is a data phar */ - if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, NULL, NULL, 2, 2)) { + if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, NULL, 2, 2)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url); return 0; } diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index a8867ed57cd5..e70dcb5e5a14 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -48,7 +48,7 @@ PHP_FUNCTION(phar_opendir) /* {{{ */ goto skip_phar; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) { php_stream_context *context = NULL; php_stream *stream; char *name; @@ -94,7 +94,7 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool return NULL; } - if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { + if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) { return NULL; } @@ -496,7 +496,7 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ phar = PHAR_G(last_phar); goto splitted; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) { /* fopen within phar, if :// is not in the url, then prepend phar:/// */ if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) { efree(arch); @@ -737,7 +737,7 @@ PHP_FUNCTION(phar_is_file) /* {{{ */ goto skip_phar; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) { phar_archive_data *phar; /* fopen within phar, if :// is not in the url, then prepend phar:/// */ @@ -795,7 +795,7 @@ PHP_FUNCTION(phar_is_link) /* {{{ */ goto skip_phar; } - if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) { + if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) { phar_archive_data *phar; /* fopen within phar, if :// is not in the url, then prepend phar:/// */ diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 02a2f09f9527..d597434d5eb3 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2163,7 +2163,7 @@ zend_string* phar_fix_filepath(const char *path, size_t path_length, bool use_cw * * This is used by phar_parse_url() */ -zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, char **entry, size_t *entry_len, int executable, int for_create) /* {{{ */ +zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, zend_string **entry, int executable, int for_create) /* {{{ */ { const char *ext_str; #ifdef PHP_WIN32 @@ -2219,13 +2219,9 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a size_t computed_entry_len = filename_len - *arch_len; /* We don't need to unixify the path on Windows, * as ext_str is derived from filename that was already unixify */ - zend_string *entry_str = phar_fix_filepath(ext_str+ext_len, computed_entry_len, false); - *entry = estrndup(ZSTR_VAL(entry_str), ZSTR_LEN(entry_str)); - *entry_len = ZSTR_LEN(entry_str); - zend_string_release_ex(entry_str, false); + *entry = phar_fix_filepath(ext_str+ext_len, computed_entry_len, false); } else { - *entry_len = 1; - *entry = estrndup("/", 1); + *entry = ZSTR_CHAR('/'); } } diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index a2b7e67a2e81..c20e5d42b313 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -474,7 +474,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, ch ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error); ZEND_ATTRIBUTE_NONNULL int phar_flush(phar_archive_data *archive, char **error); zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, bool is_complete); -zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, char **entry, size_t *entry_len, int executable, int for_create); +zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, zend_string **entry, int executable, int for_create); typedef enum { pcr_use_query, diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index f522d52ba6c4..ef997184d03d 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -419,7 +419,7 @@ PHP_METHOD(Phar, running) if ( zend_string_starts_with_literal_ci(fname, "phar://") - && SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0) + && SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0) ) { if (retphar) { RETVAL_STRINGL(ZSTR_VAL(fname), arch_len + 7); @@ -444,8 +444,8 @@ PHP_METHOD(Phar, running) */ PHP_METHOD(Phar, mount) { - char *fname, *arch = NULL, *entry = NULL, *path, *actual; - size_t fname_len, arch_len, entry_len; + char *fname, *arch = NULL, *path, *actual; + size_t fname_len, arch_len; size_t path_len, actual_len; phar_archive_data *pphar; #ifdef PHP_WIN32 @@ -476,9 +476,8 @@ PHP_METHOD(Phar, mount) } #endif - if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, NULL, NULL, 2, 0)) { - entry = NULL; - + zend_string *entry = NULL; + if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, NULL, 2, 0)) { if (path_len > 7 && !memcmp(path, "phar://", 7)) { zend_throw_exception_ex(phar_ce_PharException, 0, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path); efree(arch); @@ -505,8 +504,8 @@ PHP_METHOD(Phar, mount) zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s within phar %s failed", path, actual, arch); } - if (entry && path == entry) { - efree(entry); + if (entry && path == ZSTR_VAL(entry)) { + zend_string_release_ex(entry, false); } if (arch) { @@ -522,9 +521,9 @@ PHP_METHOD(Phar, mount) } goto carry_on; - } else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) { - path = entry; - path_len = entry_len; + } else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, 2, 0)) { + path = ZSTR_VAL(entry); + path_len = ZSTR_LEN(entry); goto carry_on2; } @@ -1078,9 +1077,9 @@ static const spl_other_handler phar_spl_foreign_handler = { */ PHP_METHOD(Phar, __construct) { - char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname; + char *fname, *alias = NULL, *error, *arch = NULL, *save_fname; size_t fname_len, alias_len = 0; - size_t arch_len, entry_len; + size_t arch_len; bool is_data; zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS; zend_long format = 0; @@ -1108,7 +1107,8 @@ PHP_METHOD(Phar, __construct) } save_fname = fname; - if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2)) { + zend_string *entry = NULL; + if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, !is_data, 2)) { /* use arch (the basename for the archive) for fname instead of fname */ /* this allows support for RecursiveDirectoryIterator of subdirectories */ #ifdef PHP_WIN32 @@ -1133,7 +1133,7 @@ PHP_METHOD(Phar, __construct) } if (entry) { - efree(entry); + zend_string_release_ex(entry, false); } if (error) { @@ -1166,7 +1166,7 @@ PHP_METHOD(Phar, __construct) zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Phar class can only be used for executable tar and zip archives"); } - efree(entry); + zend_string_release_ex(entry, false); RETURN_THROWS(); } @@ -1184,9 +1184,9 @@ PHP_METHOD(Phar, __construct) file_name_for_recursive_director_iterator_constructor = zend_string_concat3( ZEND_STRL("phar://"), phar_data->fname, phar_data->fname_len, - entry, entry_len + ZSTR_VAL(entry), ZSTR_LEN(entry) ); - efree(entry); + zend_string_release_ex(entry, false); } else { file_name_for_recursive_director_iterator_constructor = zend_string_concat2( ZEND_STRL("phar://"), @@ -1289,7 +1289,7 @@ PHP_METHOD(Phar, unlinkArchive) if ( zend_file_name && zend_string_starts_with_literal_ci(zend_file_name, "phar://") - && SUCCESS == phar_split_fname(ZSTR_VAL(zend_file_name), ZSTR_LEN(zend_file_name), &arch, &arch_len, NULL, NULL, 2, 0) + && SUCCESS == phar_split_fname(ZSTR_VAL(zend_file_name), ZSTR_LEN(zend_file_name), &arch, &arch_len, NULL, 2, 0) ) { if (arch_len == fname_len && !memcmp(arch, fname, arch_len)) { zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" cannot be unlinked from within itself", fname); @@ -4392,11 +4392,10 @@ PHP_METHOD(Phar, extractTo) /* {{{ Construct a Phar entry object */ PHP_METHOD(PharFileInfo, __construct) { - char *fname, *arch, *entry, *error; + char *fname, *arch, *error; size_t fname_len; - size_t arch_len, entry_len; + size_t arch_len; phar_entry_object *entry_obj; - phar_entry_info *entry_info; phar_archive_data *phar_data; zval arg1; @@ -4411,7 +4410,8 @@ PHP_METHOD(PharFileInfo, __construct) RETURN_THROWS(); } - if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0) == FAILURE) { + zend_string *entry = NULL; + if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, 2, 0) == FAILURE) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, "'%s' is not a valid phar archive URL (must have at least phar://filename.phar)", fname); RETURN_THROWS(); @@ -4431,16 +4431,17 @@ PHP_METHOD(PharFileInfo, __construct) RETURN_THROWS(); } - if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, true)) == NULL) { + phar_entry_info *entry_info = phar_get_entry_info_dir(phar_data, ZSTR_VAL(entry), ZSTR_LEN(entry), 1, &error, true); + if (UNEXPECTED(!entry_info)) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, - "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : ""); + "Cannot access phar file entry '%s' in archive '%s'%s%s", ZSTR_VAL(entry), arch, error ? ", " : "", error ? error : ""); + zend_string_release_ex(entry, false); efree(arch); - efree(entry); RETURN_THROWS(); } + zend_string_release_ex(entry, false); efree(arch); - efree(entry); entry_obj->entry = entry_info; if (!entry_info->is_persistent && !entry_info->is_temp_dir) { diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 6694fec9479b..4b49703b4abe 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -58,8 +58,8 @@ const php_stream_wrapper php_stream_phar_wrapper = { php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options) /* {{{ */ { php_url *resource; - char *arch = NULL, *entry = NULL, *error; - size_t arch_len, entry_len; + char *arch = NULL, *error; + size_t arch_len; if (strncasecmp(filename, "phar://", 7)) { return NULL; @@ -70,7 +70,8 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const } return NULL; } - if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len, 2, (mode[0] == 'w' ? 2 : 0)) == FAILURE) { + zend_string *entry = NULL; + if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, 2, (mode[0] == 'w' ? 2 : 0)) == FAILURE) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { if (arch && !entry) { php_stream_wrapper_log_error(wrapper, options, "phar error: no directory in \"%s\", must have at least phar://%s/ for root directory (always use full path to a new phar)", filename, arch); @@ -85,8 +86,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const resource->scheme = ZSTR_INIT_LITERAL("phar", 0); resource->host = zend_string_init(arch, arch_len, 0); efree(arch); - resource->path = zend_string_init(entry, entry_len, 0); - efree(entry); + resource->path = entry; #ifdef MBO_0 if (resource) { diff --git a/ext/phar/util.c b/ext/phar/util.c index aad6e5f7f085..1e9fedbcbb23 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -300,7 +300,7 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data goto splitted; } - if (!is_file_a_phar_wrapper || SUCCESS != phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 1, 0)) { + if (!is_file_a_phar_wrapper || SUCCESS != phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 1, 0)) { return NULL; } @@ -344,7 +344,7 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data if (ret && zend_string_starts_with_literal_ci(ret, "phar://")) { /* found phar:// */ - if (SUCCESS != phar_split_fname(ZSTR_VAL(ret), ZSTR_LEN(ret), &arch, &arch_len, NULL, NULL, 1, 0)) { + if (SUCCESS != phar_split_fname(ZSTR_VAL(ret), ZSTR_LEN(ret), &arch, &arch_len, NULL, 1, 0)) { return ret; }