diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 4674d868f490..41f45bd17f18 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -295,7 +295,6 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, zend_ulong unused; phar_archive_data *phar; phar_entry_info *entry = NULL; - uint32_t host_len; if ((resource = phar_parse_url(wrapper, path, mode, options)) == NULL) { php_stream_wrapper_log_error(wrapper, options, "phar url \"%s\" is unknown", path); @@ -320,7 +319,7 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, return NULL; } - host_len = ZSTR_LEN(resource->host); + size_t host_len = ZSTR_LEN(resource->host); phar_request_initialize(); internal_file = ZSTR_VAL(resource->path) + 1; /* strip leading "/" */ @@ -401,7 +400,6 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo char *error, *arch, *entry2; size_t arch_len, entry_len; php_url *resource = NULL; - uint32_t host_len; /* 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, &entry2, &entry_len, 2, 2)) { @@ -438,7 +436,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - host_len = ZSTR_LEN(resource->host); + size_t host_len = ZSTR_LEN(resource->host); if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), host_len, NULL, 0, &error)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path) + 1, ZSTR_VAL(resource->host), error); @@ -533,10 +531,8 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options char *error, *arch, *entry2; size_t arch_len, entry_len; php_url *resource = NULL; - uint32_t host_len; zend_string *str_key; zend_ulong unused; - uint32_t path_len; /* pre-readonly check, we need to know if this is a data phar */ if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, &entry2, &entry_len, 2, 2)) { @@ -573,7 +569,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options return 0; } - host_len = ZSTR_LEN(resource->host); + size_t host_len = ZSTR_LEN(resource->host); if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), host_len, NULL, 0, &error)) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error); @@ -582,7 +578,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options return 0; } - path_len = ZSTR_LEN(resource->path) - 1; + size_t path_len = ZSTR_LEN(resource->path) - 1; if (!(entry = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, path_len, 2, &error, 1))) { if (error) { diff --git a/ext/phar/dirstream.h b/ext/phar/dirstream.h index 4859c69fbe02..4debfecde41a 100644 --- a/ext/phar/dirstream.h +++ b/ext/phar/dirstream.h @@ -22,6 +22,8 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); #ifdef PHAR_DIRSTREAM +#include "ext/standard/url.h" + php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options); /* directory handlers */ diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index c52ee805b2b1..f1b2b0eba1e6 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -17,11 +17,10 @@ */ #include "phar_internal.h" +#include "ext/standard/php_filestat.h" +#include "ext/standard/file.h" /* For php_le_stream_context() */ -#define PHAR_FUNC(name) \ - static PHP_NAMED_FUNCTION(name) - -PHAR_FUNC(phar_opendir) /* {{{ */ +PHP_FUNCTION(phar_opendir) /* {{{ */ { char *filename; size_t filename_len; @@ -156,7 +155,7 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool return name; } -PHAR_FUNC(phar_file_get_contents) /* {{{ */ +PHP_FUNCTION(phar_file_get_contents) /* {{{ */ { zend_string *filename; zend_string *contents; @@ -233,7 +232,7 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */ } /* }}} */ -PHAR_FUNC(phar_readfile) /* {{{ */ +PHP_FUNCTION(phar_readfile) /* {{{ */ { zend_string *filename; bool use_include_path = 0; @@ -277,7 +276,7 @@ PHAR_FUNC(phar_readfile) /* {{{ */ } /* }}} */ -PHAR_FUNC(phar_fopen) /* {{{ */ +PHP_FUNCTION(phar_fopen) /* {{{ */ { zend_string *filename; char *mode; @@ -653,7 +652,7 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ /* }}} */ #define PharFileFunction(fname, funcnum, orig) \ -ZEND_NAMED_FUNCTION(fname) { \ +PHP_FUNCTION(fname) { \ if (!PHAR_G(intercepted)) { \ PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \ } else { \ @@ -725,7 +724,7 @@ PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists) PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir) /* }}} */ -PHAR_FUNC(phar_is_file) /* {{{ */ +PHP_FUNCTION(phar_is_file) /* {{{ */ { char *filename; size_t filename_len; @@ -791,7 +790,7 @@ PHAR_FUNC(phar_is_file) /* {{{ */ } /* }}} */ -PHAR_FUNC(phar_is_link) /* {{{ */ +PHP_FUNCTION(phar_is_link) /* {{{ */ { char *filename; size_t filename_len; @@ -886,7 +885,7 @@ void phar_release_functions(void) PHAR_G(orig_##func) = NULL; \ if (NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \ PHAR_G(orig_##func) = orig->internal_function.handler; \ - orig->internal_function.handler = phar_##func; \ + orig->internal_function.handler = PHP_FN(phar_##func); \ } void phar_intercept_functions_init(void) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index ff103e11686d..99767468ee71 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -19,9 +19,14 @@ #define PHAR_MAIN 1 #include "phar_internal.h" +#include "php_phar.h" #include "SAPI.h" #include "func_interceptors.h" +#include "ext/standard/crc32.h" #include "ext/standard/php_var.h" +#include "ext/standard/php_string.h" /* For php_stristr() */ +#include "ext/standard/info.h" +#include "zend_smart_str.h" static void destroy_phar_data(zval *zv); @@ -238,7 +243,7 @@ void phar_destroy_phar_data(phar_archive_data *phar) /* {{{ */ /** * Delete refcount and destruct if needed. On destruct return 1 else 0. */ -int phar_archive_delref(phar_archive_data *phar) /* {{{ */ +bool phar_archive_delref(phar_archive_data *phar) /* {{{ */ { if (phar->is_persistent) { return 0; @@ -481,7 +486,7 @@ void phar_entry_remove(phar_entry_data *idata, char **error) /* {{{ */ /** * Open an already loaded phar */ -int phar_open_parsed_phar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; #ifdef PHP_WIN32 @@ -559,7 +564,7 @@ int phar_open_parsed_phar(char *fname, size_t fname_len, char *alias, size_t ali * Attempt to serialize the data. * Callers are responsible for handling EG(exception) if one occurs. */ -void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker *tracker, int persistent) /* {{{ */ +void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker *tracker, bool persistent) /* {{{ */ { php_serialize_data_t metadata_hash; smart_str metadata_str = {0}; @@ -585,7 +590,7 @@ void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker * * Precondition: phar_metadata_tracker_has_data is true */ -int phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker *tracker, zval *metadata, int persistent, HashTable *unserialize_options, const char* method_name) /* {{{ */ +zend_result phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker *tracker, zval *metadata, bool persistent, HashTable *unserialize_options, const char* method_name) /* {{{ */ { const bool has_unserialize_options = unserialize_options != NULL && zend_hash_num_elements(unserialize_options) > 0; /* It should be impossible to create a zval in a persistent phar/entry. */ @@ -626,7 +631,7 @@ int phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker *tracker, zv /** * Check if this has any data, serialized or as a raw value. */ -bool phar_metadata_tracker_has_data(const phar_metadata_tracker *tracker, int persistent) /* {{{ */ +bool phar_metadata_tracker_has_data(const phar_metadata_tracker *tracker, bool persistent) /* {{{ */ { ZEND_ASSERT(!persistent || Z_ISUNDEF(tracker->val)); return !Z_ISUNDEF(tracker->val) || tracker->str != NULL; @@ -636,7 +641,7 @@ bool phar_metadata_tracker_has_data(const phar_metadata_tracker *tracker, int pe /** * Free memory used to track the metadata and set all fields to be null/undef. */ -void phar_metadata_tracker_free(phar_metadata_tracker *tracker, int persistent) /* {{{ */ +void phar_metadata_tracker_free(phar_metadata_tracker *tracker, bool persistent) /* {{{ */ { /* Free the string before the zval in case the zval's destructor modifies the metadata */ if (tracker->str) { @@ -658,7 +663,7 @@ void phar_metadata_tracker_free(phar_metadata_tracker *tracker, int persistent) /** * Free memory used to track the metadata and set all fields to be null/undef. */ -void phar_metadata_tracker_copy(phar_metadata_tracker *dest, const phar_metadata_tracker *source, int persistent) /* {{{ */ +void phar_metadata_tracker_copy(phar_metadata_tracker *dest, const phar_metadata_tracker *source, bool persistent) /* {{{ */ { ZEND_ASSERT(dest != source); phar_metadata_tracker_free(dest, persistent); @@ -694,7 +699,7 @@ void phar_metadata_tracker_clone(phar_metadata_tracker *tracker) /* {{{ */ * * data is the serialized zval */ -void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker, uint32_t zip_metadata_len, int persistent) /* {{{ */ +void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker, uint32_t zip_metadata_len, bool persistent) /* {{{ */ { phar_metadata_tracker_free(tracker, persistent); if (zip_metadata_len) { @@ -1302,7 +1307,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, size_t fname_len, ch /** * Create or open a phar for writing */ -int phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { const char *ext_str, *z; char *my_error; @@ -1379,7 +1384,9 @@ int phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, siz } /* }}} */ -int phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); + +zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *mydata; php_stream *fp; @@ -1402,7 +1409,7 @@ int phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, si } if (fp) { - if (phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, is_data, error) == SUCCESS) { + if (phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error) == SUCCESS) { if ((*pphar)->is_data || !PHAR_G(readonly)) { (*pphar)->is_writeable = 1; } @@ -1532,18 +1539,18 @@ int phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, si * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS * or FAILURE is returned and pphar is set to a pointer to the phar's manifest */ -int phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { php_stream *fp; zend_string *actual; - int ret, is_data = 0; + bool is_data = false; if (error) { *error = NULL; } if (!strstr(fname, ".phar")) { - is_data = 1; + is_data = true; } if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, pphar, error) == SUCCESS) { @@ -1574,7 +1581,7 @@ int phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t a fname_len = ZSTR_LEN(actual); } - ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, is_data, error); + zend_result ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error); if (actual) { zend_string_release_ex(actual, 0); @@ -1618,7 +1625,7 @@ static inline char *phar_strnstr(const char *buf, int buf_len, const char *searc * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS * or FAILURE is returned and pphar is set to a pointer to the phar's manifest */ -static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, int is_data, char **error) /* {{{ */ +static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { static const char token[] = "__HALT_COMPILER();"; static const char zip_magic[] = "PK\x03\x04"; @@ -1772,7 +1779,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char if (got > 512) { if (phar_is_tar(pos, fname)) { php_stream_rewind(fp); - return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, is_data, compression, error); + return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, compression, error); } } } @@ -1956,7 +1963,7 @@ static int phar_check_str(const char *fname, const char *ext_str, size_t ext_len * the last parameter should be set to tell the thing to assume that filename is the full path, and only to check the * extension rules, not to iterate. */ -int 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, int is_complete) /* {{{ */ +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, int is_complete) /* {{{ */ { const char *pos, *slash; @@ -2023,11 +2030,11 @@ int phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const zend_string *str_key; ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&PHAR_G(phar_fname_map), str_key, pphar) { - if (ZSTR_LEN(str_key) > (uint32_t) filename_len) { + if (ZSTR_LEN(str_key) > filename_len) { continue; } - if (!memcmp(filename, ZSTR_VAL(str_key), ZSTR_LEN(str_key)) && ((uint32_t)filename_len == ZSTR_LEN(str_key) + if (!memcmp(filename, ZSTR_VAL(str_key), ZSTR_LEN(str_key)) && (filename_len == ZSTR_LEN(str_key) || filename[ZSTR_LEN(str_key)] == '/' || filename[ZSTR_LEN(str_key)] == '\0')) { *ext_str = filename + (ZSTR_LEN(str_key) - pphar->ext_len); goto woohoo; @@ -2036,11 +2043,11 @@ int phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const if (PHAR_G(manifest_cached)) { ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&cached_phars, str_key, pphar) { - if (ZSTR_LEN(str_key) > (uint32_t) filename_len) { + if (ZSTR_LEN(str_key) > filename_len) { continue; } - if (!memcmp(filename, ZSTR_VAL(str_key), ZSTR_LEN(str_key)) && ((uint32_t)filename_len == ZSTR_LEN(str_key) + if (!memcmp(filename, ZSTR_VAL(str_key), ZSTR_LEN(str_key)) && (filename_len == ZSTR_LEN(str_key) || filename[ZSTR_LEN(str_key)] == '/' || filename[ZSTR_LEN(str_key)] == '\0')) { *ext_str = filename + (ZSTR_LEN(str_key) - pphar->ext_len); goto woohoo; @@ -2101,7 +2108,7 @@ int phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const } /* }}} */ -static int php_check_dots(const char *element, size_t n) /* {{{ */ +static bool php_check_dots(const char *element, size_t n) /* {{{ */ { for(n-- ; n != SIZE_MAX; --n) { if (element[n] != '.') { @@ -2237,7 +2244,7 @@ char *phar_fix_filepath(char *path, size_t *new_len, int use_cwd) /* {{{ */ * * This is used by phar_parse_url() */ -int 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, char **entry, size_t *entry_len, int executable, int for_create) /* {{{ */ { const char *ext_str; #ifdef PHP_WIN32 @@ -2314,7 +2321,7 @@ int phar_split_fname(const char *filename, size_t filename_len, char **arch, siz * Invoked when a user calls Phar::mapPhar() from within an executing .phar * to set up its manifest directly */ -int phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* {{{ */ +zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* {{{ */ { if (error) { *error = NULL; @@ -2362,7 +2369,7 @@ int phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* fname = actual; } - int ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, REPORT_ERRORS, NULL, 0, error); + zend_result ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, REPORT_ERRORS, NULL, error); if (actual) { zend_string_release_ex(actual, 0); @@ -2375,10 +2382,8 @@ int phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* /** * Validate the CRC32 of a file opened from within the phar */ -int phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip) /* {{{ */ +zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip) /* {{{ */ { - uint32_t crc = php_crc32_bulk_init(); - int len = idata->internal_file->uncompressed_filesize, ret; php_stream *fp = idata->fp; phar_entry_info *entry = idata->internal_file; @@ -2443,7 +2448,8 @@ int phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, php_stream_seek(fp, idata->zero, SEEK_SET); - ret = php_crc32_stream_bulk_update(&crc, fp, len); + uint32_t crc = php_crc32_bulk_init(); + zend_result ret = php_crc32_stream_bulk_update(&crc, fp, idata->internal_file->uncompressed_filesize); php_stream_seek(fp, idata->zero, SEEK_SET); diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 625b8f1f16f9..eb836ac691ad 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -24,39 +24,9 @@ #include #include "php.h" #include "tar.h" -#include "php_ini.h" -#include "zend_constants.h" -#include "zend_execute.h" -#include "zend_exceptions.h" +#include "pharzip.h" #include "zend_hash.h" -#include "zend_interfaces.h" -#include "zend_operators.h" -#include "zend_sort.h" -#include "zend_vm.h" -#include "zend_smart_str.h" -#include "main/php_streams.h" -#include "main/streams/php_stream_plain_wrapper.h" -#include "main/SAPI.h" -#include "main/php_main.h" -#include "main/php_open_temporary_file.h" -#include "ext/standard/info.h" -#include "ext/standard/basic_functions.h" -#include "ext/standard/file.h" -#include "ext/standard/php_string.h" -#include "ext/standard/url.h" -#include "ext/standard/crc32.h" -#include "ext/standard/md5.h" -#include "ext/standard/sha1.h" -#include "ext/standard/php_var.h" -#include "ext/standard/php_versioning.h" -#include "Zend/zend_virtual_cwd.h" -#include "ext/spl/spl_array.h" #include "ext/spl/spl_directory.h" -#include "ext/spl/spl_exceptions.h" -#include "ext/spl/spl_iterators.h" -#include "php_phar.h" -#include "ext/hash/php_hash.h" -#include "ext/hash/php_hash_sha.h" /* PHP_ because this is public information via MINFO */ #define PHP_PHAR_API_VERSION "1.1.1" @@ -193,8 +163,6 @@ ZEND_EXTERN_MODULE_GLOBALS(phar) ZEND_TSRMLS_CACHE_EXTERN() #endif -#include "pharzip.h" - typedef union _phar_archive_object phar_archive_object; typedef union _phar_entry_object phar_entry_object; @@ -331,7 +299,7 @@ struct _phar_entry_fp { phar_entry_fp_info *manifest; }; -static inline php_stream *phar_get_entrypfp(phar_entry_info *entry) +static inline php_stream *phar_get_entrypfp(const phar_entry_info *entry) { if (!entry->is_persistent) { return entry->phar->fp; @@ -339,35 +307,7 @@ static inline php_stream *phar_get_entrypfp(phar_entry_info *entry) return PHAR_G(cached_fp)[entry->phar->phar_pos].fp; } -static inline php_stream *phar_get_entrypufp(phar_entry_info *entry) -{ - if (!entry->is_persistent) { - return entry->phar->ufp; - } - return PHAR_G(cached_fp)[entry->phar->phar_pos].ufp; -} - -static inline void phar_set_entrypfp(phar_entry_info *entry, php_stream *fp) -{ - if (!entry->phar->is_persistent) { - entry->phar->fp = fp; - return; - } - - PHAR_G(cached_fp)[entry->phar->phar_pos].fp = fp; -} - -static inline void phar_set_entrypufp(phar_entry_info *entry, php_stream *fp) -{ - if (!entry->phar->is_persistent) { - entry->phar->ufp = fp; - return; - } - - PHAR_G(cached_fp)[entry->phar->phar_pos].ufp = fp; -} - -static inline php_stream *phar_get_pharfp(phar_archive_data *phar) +static inline php_stream *phar_get_pharfp(const phar_archive_data *phar) { if (!phar->is_persistent) { return phar->fp; @@ -375,49 +315,7 @@ static inline php_stream *phar_get_pharfp(phar_archive_data *phar) return PHAR_G(cached_fp)[phar->phar_pos].fp; } -static inline php_stream *phar_get_pharufp(phar_archive_data *phar) -{ - if (!phar->is_persistent) { - return phar->ufp; - } - return PHAR_G(cached_fp)[phar->phar_pos].ufp; -} - -static inline void phar_set_pharfp(phar_archive_data *phar, php_stream *fp) -{ - if (!phar->is_persistent) { - phar->fp = fp; - return; - } - - PHAR_G(cached_fp)[phar->phar_pos].fp = fp; -} - -static inline void phar_set_pharufp(phar_archive_data *phar, php_stream *fp) -{ - if (!phar->is_persistent) { - phar->ufp = fp; - return; - } - - PHAR_G(cached_fp)[phar->phar_pos].ufp = fp; -} - -static inline void phar_set_fp_type(phar_entry_info *entry, enum phar_fp_type type, zend_off_t offset) -{ - phar_entry_fp_info *data; - - if (!entry->is_persistent) { - entry->fp_type = type; - entry->offset = offset; - return; - } - data = &(PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos]); - data->fp_type = type; - data->offset = offset; -} - -static inline enum phar_fp_type phar_get_fp_type(phar_entry_info *entry) +static inline enum phar_fp_type phar_get_fp_type(const phar_entry_info *entry) { if (!entry->is_persistent) { return entry->fp_type; @@ -425,19 +323,6 @@ static inline enum phar_fp_type phar_get_fp_type(phar_entry_info *entry) return PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].fp_type; } -static inline zend_off_t phar_get_fp_offset(phar_entry_info *entry) -{ - if (!entry->is_persistent) { - return entry->offset; - } - if (PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].fp_type == PHAR_FP) { - if (!PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].offset) { - PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].offset = entry->offset; - } - } - return PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].offset; -} - #define PHAR_MIME_PHP '\0' #define PHAR_MIME_PHPS '\1' #define PHAR_MIME_OTHER '\2' @@ -487,10 +372,8 @@ static inline void phar_unixify_path_separators(char *path, size_t path_len) } } #endif -/** - * validate an alias, returns 1 for success, 0 for failure - */ -static inline int phar_validate_alias(const char *alias, size_t alias_len) /* {{{ */ + +static inline bool phar_validate_alias(const char *alias, size_t alias_len) /* {{{ */ { return !(memchr(alias, '/', alias_len) || memchr(alias, '\\', alias_len) || memchr(alias, ':', alias_len) || memchr(alias, ';', alias_len) || memchr(alias, '\n', alias_len) || memchr(alias, '\r', alias_len)); @@ -522,16 +405,15 @@ void phar_request_initialize(void); void phar_object_init(void); void phar_destroy_phar_data(phar_archive_data *phar); -int phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip); -int phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); -int phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -int phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -int phar_open_executed_filename(char *alias, size_t alias_len, char **error); -int phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len); -int phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error); -int phar_open_parsed_phar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -int phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, char *fname, char **signature, size_t *signature_len, char **error); -int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error); +zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip); +zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); +zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); +zend_result phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len); +zend_result phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error); +zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, char *fname, char **signature, size_t *signature_len, char **error); +zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error); /* utility functions */ zend_string *phar_create_default_stub(const char *index_php, const char *web_index, char **error); @@ -540,33 +422,31 @@ char *phar_compress_filter(phar_entry_info * entry, int return_unknown); /* void phar_remove_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len); */ void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len); -int phar_mount_entry(phar_archive_data *phar, char *filename, size_t filename_len, char *path, size_t path_len); +zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t filename_len, char *path, size_t path_len); zend_string *phar_find_in_include_path(zend_string *file, phar_archive_data **pphar); char *phar_fix_filepath(char *path, size_t *new_len, int use_cwd); phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, char **error); -void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker, uint32_t zip_metadata_len, int persistent); -bool phar_metadata_tracker_has_data(const phar_metadata_tracker* tracker, int persistent); +void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker, uint32_t zip_metadata_len, bool persistent); +bool phar_metadata_tracker_has_data(const phar_metadata_tracker* tracker, bool persistent); /* If this has data, free it and set all values to undefined. */ -void phar_metadata_tracker_free(phar_metadata_tracker* val, int persistent); -void phar_metadata_tracker_copy(phar_metadata_tracker* dest, const phar_metadata_tracker *source, int persistent); +void phar_metadata_tracker_free(phar_metadata_tracker* val, bool persistent); +void phar_metadata_tracker_copy(phar_metadata_tracker* dest, const phar_metadata_tracker *source, bool persistent); void phar_metadata_tracker_clone(phar_metadata_tracker* tracker); -void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker* tracker, int persistent); -int phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker* tracker, zval *value, int persistent, HashTable *unserialize_options, const char* method_name); +void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker* tracker, bool persistent); +zend_result phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker* tracker, zval *value, bool persistent, HashTable *unserialize_options, const char* method_name); void destroy_phar_manifest_entry(zval *zv); int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links); php_stream *phar_get_efp(phar_entry_info *entry, int follow_links); -int phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error); -int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links); +zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error); +zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links); phar_entry_info *phar_get_link_source(phar_entry_info *entry); -int phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error); -int phar_separate_entry_fp(phar_entry_info *entry, char **error); -int phar_open_archive_fp(phar_archive_data *phar); -int phar_copy_on_write(phar_archive_data **pphar); +zend_result phar_open_archive_fp(phar_archive_data *phar); +zend_result phar_copy_on_write(phar_archive_data **pphar); /* tar functions in tar.c */ -int phar_is_tar(char *buf, char *fname); -int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, int is_data, uint32_t compression, char **error); -int phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error); +bool phar_is_tar(char *buf, char *fname); +zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error); +zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error); int phar_tar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int defaultstub, char **error); /* zip functions in zip.c */ @@ -575,23 +455,22 @@ int phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t a int phar_zip_flush(phar_archive_data *archive, char *user_stub, zend_long len, int defaultstub, char **error); #ifdef PHAR_MAIN -static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, int is_data, char **error); extern const php_stream_wrapper php_stream_phar_wrapper; #else extern HashTable cached_phars; extern HashTable cached_alias; #endif -int phar_archive_delref(phar_archive_data *phar); +bool phar_archive_delref(phar_archive_data *phar); void phar_entry_delref(phar_entry_data *idata); phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t path_len, char **error, int security); phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, int security); phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security); -int phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security); +zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security); int phar_flush(phar_archive_data *archive, char *user_stub, zend_long len, int convert, char **error); -int 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, int is_complete); -int 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_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, int 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); typedef enum { pcr_use_query, diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 688e3981e67d..e23a3eabc2a0 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -20,6 +20,14 @@ #include "phar_internal.h" #include "func_interceptors.h" #include "phar_object_arginfo.h" +#include "ext/spl/spl_array.h" +#include "ext/spl/spl_exceptions.h" +#include "ext/spl/spl_iterators.h" +#include "ext/standard/php_var.h" +#include "main/SAPI.h" +#include "zend_exceptions.h" +#include "zend_interfaces.h" +#include "zend_exceptions.h" static zend_class_entry *phar_ce_archive; static zend_class_entry *phar_ce_data; @@ -1922,7 +1930,7 @@ PHP_METHOD(Phar, isFileFormat) } /* }}} */ -static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp) /* {{{ */ +static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *fp) /* {{{ */ { char *error; zend_off_t offset; @@ -2600,12 +2608,11 @@ PHP_METHOD(Phar, isWritable) /* {{{ Deletes a named file within the archive. */ PHP_METHOD(Phar, delete) { - char *fname; - size_t fname_len; + zend_string *file_name; char *error; phar_entry_info *entry; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file_name) == FAILURE) { RETURN_THROWS(); } @@ -2621,7 +2628,7 @@ PHP_METHOD(Phar, delete) zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname); RETURN_THROWS(); } - if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) { + if (NULL != (entry = zend_hash_find_ptr(&phar_obj->archive->manifest, file_name))) { if (entry->is_deleted) { /* entry is deleted, but has not been flushed to disk yet */ RETURN_TRUE; @@ -2631,7 +2638,7 @@ PHP_METHOD(Phar, delete) phar_obj->archive->is_modified = 1; } } else { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be deleted", fname); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be deleted", ZSTR_VAL(file_name)); RETURN_THROWS(); } @@ -2679,12 +2686,13 @@ PHP_METHOD(Phar, getPath) */ PHP_METHOD(Phar, setAlias) { - char *alias, *error, *oldalias; + zend_string *new_alias = NULL; + char *error, *oldalias; phar_archive_data *fd_ptr; - size_t alias_len, oldalias_len; + size_t oldalias_len; int old_temp, readd = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &alias, &alias_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &new_alias) == FAILURE) { RETURN_THROWS(); } @@ -2711,12 +2719,12 @@ PHP_METHOD(Phar, setAlias) RETURN_THROWS(); } - if (alias_len == phar_obj->archive->alias_len && memcmp(phar_obj->archive->alias, alias, alias_len) == 0) { + if (zend_string_equals_cstr(new_alias, phar_obj->archive->alias, phar_obj->archive->alias_len)) { RETURN_TRUE; } - if (alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { - spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", alias, fd_ptr->fname); - if (SUCCESS == phar_free_alias(fd_ptr, alias, alias_len)) { + if (NULL != (fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), new_alias))) { + spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", ZSTR_VAL(new_alias), fd_ptr->fname); + if (SUCCESS == phar_free_alias(fd_ptr, ZSTR_VAL(new_alias), ZSTR_LEN(new_alias))) { efree(error); goto valid_alias; } @@ -2724,9 +2732,9 @@ PHP_METHOD(Phar, setAlias) efree(error); RETURN_THROWS(); } - if (!phar_validate_alias(alias, alias_len)) { + if (!phar_validate_alias(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias))) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "Invalid alias \"%s\" specified for phar \"%s\"", alias, phar_obj->archive->fname); + "Invalid alias \"%s\" specified for phar \"%s\"", ZSTR_VAL(new_alias), phar_obj->archive->fname); RETURN_THROWS(); } valid_alias: @@ -2743,13 +2751,8 @@ PHP_METHOD(Phar, setAlias) oldalias_len = phar_obj->archive->alias_len; old_temp = phar_obj->archive->is_temporary_alias; - if (alias_len) { - phar_obj->archive->alias = estrndup(alias, alias_len); - } else { - phar_obj->archive->alias = NULL; - } - - phar_obj->archive->alias_len = alias_len; + phar_obj->archive->alias = estrndup(ZSTR_VAL(new_alias), ZSTR_LEN(new_alias)); + phar_obj->archive->alias_len = ZSTR_LEN(new_alias); phar_obj->archive->is_temporary_alias = 0; phar_flush(phar_obj->archive, NULL, 0, 0, &error); @@ -2765,7 +2768,7 @@ PHP_METHOD(Phar, setAlias) RETURN_THROWS(); } - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, phar_obj->archive); + zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), new_alias, phar_obj->archive); if (oldalias) { efree(oldalias); @@ -3408,13 +3411,13 @@ PHP_METHOD(Phar, decompressFiles) /* {{{ copy a file internal to the phar archive to another new file within the phar */ PHP_METHOD(Phar, copy) { - char *oldfile, *newfile, *error; + char *error; const char *pcr_error; - size_t oldfile_len, newfile_len; phar_entry_info *oldentry, newentry = {0}, *temp; - size_t tmp_len = 0; + zend_string *new_file = NULL; + zend_string *old_file = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &oldfile, &oldfile_len, &newfile, &newfile_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "PP", &old_file, &new_file) == FAILURE) { RETURN_THROWS(); } @@ -3422,43 +3425,43 @@ PHP_METHOD(Phar, copy) if (PHAR_G(readonly) && !phar_obj->archive->is_data) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "Cannot copy \"%s\" to \"%s\", phar is read-only", oldfile, newfile); + "Cannot copy \"%s\" to \"%s\", phar is read-only", ZSTR_VAL(old_file), ZSTR_VAL(new_file)); RETURN_THROWS(); } - if (oldfile_len >= sizeof(".phar")-1 && !memcmp(oldfile, ".phar", sizeof(".phar")-1)) { + if (zend_string_starts_with_literal(old_file, ".phar")) { /* can't copy a meta file */ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "file \"%s\" cannot be copied to file \"%s\", cannot copy Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname); + "file \"%s\" cannot be copied to file \"%s\", cannot copy Phar meta-file in %s", ZSTR_VAL(old_file), ZSTR_VAL(new_file), phar_obj->archive->fname); RETURN_THROWS(); } - if (newfile_len >= sizeof(".phar")-1 && !memcmp(newfile, ".phar", sizeof(".phar")-1)) { + if (zend_string_starts_with_literal(new_file, ".phar")) { /* can't copy a meta file */ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "file \"%s\" cannot be copied to file \"%s\", cannot copy to Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname); + "file \"%s\" cannot be copied to file \"%s\", cannot copy to Phar meta-file in %s", ZSTR_VAL(old_file), ZSTR_VAL(new_file), phar_obj->archive->fname); RETURN_THROWS(); } - if (NULL == (oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len)) || oldentry->is_deleted) { + if (NULL == (oldentry = zend_hash_find_ptr(&phar_obj->archive->manifest, old_file)) || oldentry->is_deleted) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "file \"%s\" cannot be copied to file \"%s\", file does not exist in %s", oldfile, newfile, phar_obj->archive->fname); + "file \"%s\" cannot be copied to file \"%s\", file does not exist in %s", ZSTR_VAL(old_file), ZSTR_VAL(new_file), phar_obj->archive->fname); RETURN_THROWS(); } - if (NULL != (temp = zend_hash_str_find_ptr(&phar_obj->archive->manifest, newfile, (uint32_t) newfile_len)) && !temp->is_deleted) { + if (NULL != (temp = zend_hash_find_ptr(&phar_obj->archive->manifest, new_file)) && !temp->is_deleted) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "file \"%s\" cannot be copied to file \"%s\", file must not already exist in phar %s", oldfile, newfile, phar_obj->archive->fname); + "file \"%s\" cannot be copied to file \"%s\", file must not already exist in phar %s", ZSTR_VAL(old_file), ZSTR_VAL(new_file), phar_obj->archive->fname); RETURN_THROWS(); } - tmp_len = newfile_len; - if (phar_path_check(&newfile, &tmp_len, &pcr_error) > pcr_is_ok) { + size_t tmp_len = ZSTR_LEN(new_file); + char *tmp_new_file = ZSTR_VAL(new_file); + if (phar_path_check(&tmp_new_file, &tmp_len, &pcr_error) > pcr_is_ok) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "file \"%s\" contains invalid characters %s, cannot be copied from \"%s\" in phar %s", newfile, pcr_error, oldfile, phar_obj->archive->fname); + "file \"%s\" contains invalid characters %s, cannot be copied from \"%s\" in phar %s", ZSTR_VAL(new_file), pcr_error, ZSTR_VAL(old_file), phar_obj->archive->fname); RETURN_THROWS(); } - newfile_len = tmp_len; if (phar_obj->archive->is_persistent) { if (FAILURE == phar_copy_on_write(&(phar_obj->archive))) { @@ -3466,15 +3469,15 @@ PHP_METHOD(Phar, copy) RETURN_THROWS(); } /* re-populate with copied-on-write entry */ - oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len); + oldentry = zend_hash_find_ptr(&phar_obj->archive->manifest, old_file); } memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info)); phar_metadata_tracker_clone(&newentry.metadata_tracker); - newentry.filename = estrndup(newfile, newfile_len); - newentry.filename_len = newfile_len; + newentry.filename = estrndup(tmp_new_file, tmp_len); + newentry.filename_len = tmp_len; newentry.fp_refcount = 0; if (oldentry->fp_type != PHAR_FP) { @@ -3487,7 +3490,7 @@ PHP_METHOD(Phar, copy) } } - zend_hash_str_add_mem(&oldentry->phar->manifest, newfile, newfile_len, &newentry, sizeof(phar_entry_info)); + zend_hash_str_add_mem(&oldentry->phar->manifest, ZSTR_VAL(new_file), tmp_len, &newentry, sizeof(phar_entry_info)); phar_obj->archive->is_modified = 1; phar_flush(phar_obj->archive, 0, 0, 0, &error); @@ -3503,34 +3506,30 @@ PHP_METHOD(Phar, copy) /* {{{ determines whether a file exists in the phar */ PHP_METHOD(Phar, offsetExists) { - char *fname; - size_t fname_len; + zend_string *file_name; phar_entry_info *entry; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file_name) == FAILURE) { RETURN_THROWS(); } PHAR_ARCHIVE_OBJECT(); - if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) { - if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) { + if (zend_hash_exists(&phar_obj->archive->manifest, file_name)) { + if (NULL != (entry = zend_hash_find_ptr(&phar_obj->archive->manifest, file_name))) { if (entry->is_deleted) { /* entry is deleted, but has not been flushed to disk yet */ RETURN_FALSE; } } - if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) { + if (zend_string_starts_with_literal(file_name, ".phar")) { /* none of these are real files, so they don't exist */ RETURN_FALSE; } RETURN_TRUE; } else { - if (zend_hash_str_exists(&phar_obj->archive->virtual_dirs, fname, (uint32_t) fname_len)) { - RETURN_TRUE; - } - RETURN_FALSE; + RETURN_BOOL(zend_hash_exists(&phar_obj->archive->virtual_dirs, file_name)); } } /* }}} */ @@ -3538,31 +3537,31 @@ PHP_METHOD(Phar, offsetExists) /* {{{ get a PharFileInfo object for a specific file */ PHP_METHOD(Phar, offsetGet) { - char *fname, *error; - size_t fname_len; + char *error; phar_entry_info *entry; + zend_string *file_name = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file_name) == FAILURE) { RETURN_THROWS(); } PHAR_ARCHIVE_OBJECT(); /* security is 0 here so that we can get a better error message than "entry doesn't exist" */ - if (!(entry = phar_get_entry_info_dir(phar_obj->archive, fname, fname_len, 1, &error, 0))) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:""); + if (!(entry = phar_get_entry_info_dir(phar_obj->archive, ZSTR_VAL(file_name), ZSTR_LEN(file_name), 1, &error, 0))) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist%s%s", ZSTR_VAL(file_name), error?", ":"", error?error:""); } else { - if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { + if (zend_string_equals_literal(file_name, ".phar/stub.php")) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use getStub", phar_obj->archive->fname); RETURN_THROWS(); } - if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) { + if (zend_string_equals_literal(file_name, ".phar/alias.txt")) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use getAlias", phar_obj->archive->fname); RETURN_THROWS(); } - if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) { + if (zend_string_starts_with_literal(file_name, ".phar")) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot directly get any files or directories in magic \".phar\" directory"); RETURN_THROWS(); } @@ -3572,7 +3571,7 @@ PHP_METHOD(Phar, offsetGet) efree(entry); } - zend_string *sfname = strpprintf(0, "phar://%s/%s", phar_obj->archive->fname, fname); + zend_string *sfname = strpprintf(0, "phar://%s/%s", phar_obj->archive->fname, ZSTR_VAL(file_name)); zval zfname; ZVAL_NEW_STR(&zfname, sfname); @@ -3587,11 +3586,9 @@ PHP_METHOD(Phar, offsetGet) /* }}} */ /* {{{ add a file within the phar archive from a string or resource */ -static void phar_add_file(phar_archive_data **pphar, char *filename, size_t filename_len, char *cont_str, size_t cont_len, zval *zresource) +static void phar_add_file(phar_archive_data **pphar, zend_string *file_name, const zend_string *content, zval *zresource) { - size_t start_pos=0; char *error; - size_t contents_len; phar_entry_data *data; php_stream *contents_file = NULL; php_stream_statbuf ssb; @@ -3600,14 +3597,21 @@ static void phar_add_file(phar_archive_data **pphar, char *filename, size_t file ALLOCA_FLAG(filename_use_heap) #endif - if (filename_len >= sizeof(".phar")-1) { - start_pos = '/' == filename[0]; /* account for any leading slash: multiple-leads handled elsewhere */ - if (!memcmp(&filename[start_pos], ".phar", sizeof(".phar")-1) && (filename[start_pos+5] == '/' || filename[start_pos+5] == '\\' || filename[start_pos+5] == '\0')) { + if ( + zend_string_starts_with_literal(file_name, ".phar") + || zend_string_starts_with_literal(file_name, "/.phar") + ) { + size_t prefix_len = (ZSTR_VAL(file_name)[0] == '/') + sizeof(".phar")-1; + char next_char = ZSTR_VAL(file_name)[prefix_len]; + if (next_char == '/' || next_char == '\\' || next_char == '\0') { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create any files in magic \".phar\" directory"); return; } } + /* TODO How to handle Windows path normalisation with zend_string ? */ + char *filename = ZSTR_VAL(file_name); + size_t filename_len = ZSTR_LEN(file_name); #ifdef PHP_WIN32 save_filename = filename; if (memchr(filename, '\\', filename_len)) { @@ -3631,9 +3635,11 @@ static void phar_add_file(phar_archive_data **pphar, char *filename, size_t file } if (!data->internal_file->is_dir) { - if (cont_str) { - contents_len = php_stream_write(data->fp, cont_str, cont_len); - if (contents_len != cont_len) { + size_t contents_len = 0; + if (content) { + contents_len = ZSTR_LEN(content); + size_t written_len = php_stream_write(data->fp, ZSTR_VAL(content), ZSTR_LEN(content)); + if (written_len != contents_len) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s could not be written to", filename); goto finish; } @@ -3682,17 +3688,17 @@ finish: ; /* }}} */ /* {{{ create a directory within the phar archive */ -static void phar_mkdir(phar_archive_data **pphar, char *dirname, size_t dirname_len) +static void phar_mkdir(phar_archive_data **pphar, zend_string *dir_name) { char *error; phar_entry_data *data; - if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, dirname, dirname_len, "w+b", 2, &error, 1))) { + if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, ZSTR_VAL(dir_name), ZSTR_LEN(dir_name), "w+b", 2, &error, 1))) { if (error) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created: %s", dirname, error); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created: %s", ZSTR_VAL(dir_name), error); efree(error); } else { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created", dirname); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created", ZSTR_VAL(dir_name)); } return; @@ -3719,12 +3725,12 @@ static void phar_mkdir(phar_archive_data **pphar, char *dirname, size_t dirname_ /* {{{ set the contents of an internal file to those of an external file */ PHP_METHOD(Phar, offsetSet) { - char *fname, *cont_str = NULL; - size_t fname_len, cont_len; zval *zresource = NULL; + zend_string *file_name = NULL; + zend_string *file_content = NULL; - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "pr", &fname, &fname_len, &zresource) == FAILURE - && zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &fname, &fname_len, &cont_str, &cont_len) == FAILURE) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "Pr", &file_name, &zresource) == FAILURE + && zend_parse_parameters(ZEND_NUM_ARGS(), "PS", &file_name, &file_content) == FAILURE) { RETURN_THROWS(); } @@ -3735,33 +3741,33 @@ PHP_METHOD(Phar, offsetSet) RETURN_THROWS(); } - if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { + if (zend_string_equals_literal(file_name, ".phar/stub.php")) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set stub \".phar/stub.php\" directly in phar \"%s\", use setStub", phar_obj->archive->fname); RETURN_THROWS(); } - if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) { + if (zend_string_equals_literal(file_name, ".phar/alias.txt")) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set alias \".phar/alias.txt\" directly in phar \"%s\", use setAlias", phar_obj->archive->fname); RETURN_THROWS(); } - if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) { + if (zend_string_starts_with_literal(file_name, ".phar")) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set any files or directories in magic \".phar\" directory"); RETURN_THROWS(); } - phar_add_file(&(phar_obj->archive), fname, fname_len, cont_str, cont_len, zresource); + phar_add_file(&(phar_obj->archive), file_name, file_content, zresource); } /* }}} */ /* {{{ remove a file from a phar */ PHP_METHOD(Phar, offsetUnset) { - char *fname, *error; - size_t fname_len; + char *error; + zend_string *file_name; phar_entry_info *entry; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file_name) == FAILURE) { RETURN_THROWS(); } @@ -3772,8 +3778,8 @@ PHP_METHOD(Phar, offsetUnset) RETURN_THROWS(); } - if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) { - if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) { + if (zend_hash_exists(&phar_obj->archive->manifest, file_name)) { + if (NULL != (entry = zend_hash_find_ptr(&phar_obj->archive->manifest, file_name))) { if (entry->is_deleted) { /* entry is deleted, but has not been flushed to disk yet */ return; @@ -3785,7 +3791,7 @@ PHP_METHOD(Phar, offsetUnset) RETURN_THROWS(); } /* re-populate entry after copy on write */ - entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len); + entry = zend_hash_find_ptr(&phar_obj->archive->manifest, file_name); } entry->is_modified = 0; entry->is_deleted = 1; @@ -3804,55 +3810,53 @@ PHP_METHOD(Phar, offsetUnset) /* {{{ Adds an empty directory to the phar archive */ PHP_METHOD(Phar, addEmptyDir) { - char *dirname; - size_t dirname_len; + zend_string *dir_name; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &dirname, &dirname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &dir_name) == FAILURE) { RETURN_THROWS(); } PHAR_ARCHIVE_OBJECT(); - if (dirname_len >= sizeof(".phar")-1 && !memcmp(dirname, ".phar", sizeof(".phar")-1)) { + if (zend_string_starts_with_literal(dir_name, ".phar")) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create a directory in magic \".phar\" directory"); RETURN_THROWS(); } - phar_mkdir(&phar_obj->archive, dirname, dirname_len); + phar_mkdir(&phar_obj->archive, dir_name); } /* }}} */ /* {{{ Adds a file to the archive using the filename, or the second parameter as the name within the archive */ PHP_METHOD(Phar, addFile) { - char *fname, *localname = NULL; - size_t fname_len, localname_len = 0; + zend_string *file_name; + zend_string *local_name = NULL; php_stream *resource; zval zresource; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!", &fname, &fname_len, &localname, &localname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|S!", &file_name, &local_name) == FAILURE) { RETURN_THROWS(); } PHAR_ARCHIVE_OBJECT(); - if (!strstr(fname, "://") && php_check_open_basedir(fname)) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, open_basedir restrictions prevent this", fname); + if (!strstr(ZSTR_VAL(file_name), "://") && php_check_open_basedir(ZSTR_VAL(file_name))) { + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, open_basedir restrictions prevent this", ZSTR_VAL(file_name)); RETURN_THROWS(); } - if (!(resource = php_stream_open_wrapper(fname, "rb", 0, NULL))) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive", fname); + if (!(resource = php_stream_open_wrapper(ZSTR_VAL(file_name), "rb", 0, NULL))) { + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive", ZSTR_VAL(file_name)); RETURN_THROWS(); } - if (localname) { - fname = localname; - fname_len = localname_len; + if (local_name) { + file_name = local_name; } php_stream_to_zval(resource, &zresource); - phar_add_file(&(phar_obj->archive), fname, fname_len, NULL, 0, &zresource); + phar_add_file(&(phar_obj->archive), file_name, NULL, &zresource); zval_ptr_dtor(&zresource); } /* }}} */ @@ -3860,16 +3864,16 @@ PHP_METHOD(Phar, addFile) /* {{{ Adds a file to the archive using its contents as a string */ PHP_METHOD(Phar, addFromString) { - char *localname, *cont_str; - size_t localname_len, cont_len; + zend_string *local_name = NULL; + zend_string *file_content = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &localname, &localname_len, &cont_str, &cont_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "PS", &local_name, &file_content) == FAILURE) { RETURN_THROWS(); } PHAR_ARCHIVE_OBJECT(); - phar_add_file(&(phar_obj->archive), localname, localname_len, cont_str, cont_len, NULL); + phar_add_file(&(phar_obj->archive), local_name, file_content, NULL); } /* }}} */ @@ -4004,7 +4008,7 @@ PHP_METHOD(Phar, getMetadata) /* }}} */ /* {{{ Modifies the phar metadata or throws */ -static int serialize_metadata_or_throw(phar_metadata_tracker *tracker, int persistent, zval *metadata) +static zend_result serialize_metadata_or_throw(phar_metadata_tracker *tracker, int persistent, zval *metadata) { php_serialize_data_t metadata_hash; smart_str main_metadata_str = {0}; @@ -4105,7 +4109,7 @@ PHP_METHOD(Phar, delMetadata) } /* }}} */ -static int phar_extract_file(bool overwrite, phar_entry_info *entry, char *dest, size_t dest_len, char **error) /* {{{ */ +static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, char *dest, size_t dest_len, char **error) /* {{{ */ { php_stream_statbuf ssb; size_t len; @@ -4259,7 +4263,7 @@ static int phar_extract_file(bool overwrite, phar_entry_info *entry, char *dest, } } - if (FAILURE == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { + if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", entry->filename, fullpath); efree(fullpath); php_stream_close(fp); diff --git a/ext/phar/phar_object.stub.php b/ext/phar/phar_object.stub.php index e20b575d87a5..ae5bd69c32f4 100644 --- a/ext/phar/phar_object.stub.php +++ b/ext/phar/phar_object.stub.php @@ -187,10 +187,10 @@ public function offsetSet($localName, $value): void {} public function offsetUnset($localName): void {} /** @tentative-return-type */ - public function setAlias(string $alias): bool {} + public function setAlias(string $alias): true {} /** @tentative-return-type */ - public function setDefaultStub(?string $index = null, ?string $webIndex = null): bool {} + public function setDefaultStub(?string $index = null, ?string $webIndex = null): true {} /** @tentative-return-type */ public function setMetadata(mixed $metadata): void {} diff --git a/ext/phar/phar_object_arginfo.h b/ext/phar/phar_object_arginfo.h index 16482611560b..3111bc260f4a 100644 --- a/ext/phar/phar_object_arginfo.h +++ b/ext/phar/phar_object_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 4182a1159f6cf8a0d71a7814d0435b5e2be29276 */ + * Stub hash: 031dc8f07d2d9bac4a5f82f4ac2c5b3da5995405 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Phar___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -133,11 +133,11 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Phar_offsetUnset ZEND_ARG_INFO(0, localName) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Phar_setAlias, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Phar_setAlias, 0, 1, IS_TRUE, 0) ZEND_ARG_TYPE_INFO(0, alias, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Phar_setDefaultStub, 0, 0, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Phar_setDefaultStub, 0, 0, IS_TRUE, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, index, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, webIndex, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -302,9 +302,14 @@ ZEND_END_ARG_INFO() #define arginfo_class_PharData_offsetUnset arginfo_class_Phar_offsetUnset -#define arginfo_class_PharData_setAlias arginfo_class_Phar_setAlias +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_PharData_setAlias, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, alias, IS_STRING, 0) +ZEND_END_ARG_INFO() -#define arginfo_class_PharData_setDefaultStub arginfo_class_Phar_setDefaultStub +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_PharData_setDefaultStub, 0, 0, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, index, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, webIndex, IS_STRING, 1, "null") +ZEND_END_ARG_INFO() #define arginfo_class_PharData_setMetadata arginfo_class_Phar_setMetadata diff --git a/ext/phar/php_phar.h b/ext/phar/php_phar.h index 9825909ee22f..66db4c06829c 100644 --- a/ext/phar/php_phar.h +++ b/ext/phar/php_phar.h @@ -32,6 +32,6 @@ extern zend_module_entry phar_module_entry; #define PHP_PHAR_API PHPAPI #endif -PHP_PHAR_API int phar_resolve_alias(char *alias, size_t alias_len, char **filename, size_t *filename_len); +PHP_PHAR_API zend_result phar_resolve_alias(char *alias, size_t alias_len, char **filename, size_t *filename_len); #endif /* PHP_PHAR_H */ diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 79f02ff70db5..f5e1d9514c72 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -168,7 +168,6 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha php_url *resource = NULL; php_stream *fpf; zval *pzoption, *metadata; - uint32_t host_len; if ((resource = phar_parse_url(wrapper, path, mode, options)) == NULL) { return NULL; @@ -187,7 +186,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha return NULL; } - host_len = ZSTR_LEN(resource->host); + size_t host_len = ZSTR_LEN(resource->host); phar_request_initialize(); /* strip leading "/" */ @@ -565,7 +564,6 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f char *internal_file, *error; phar_archive_data *phar; phar_entry_info *entry; - uint32_t host_len; size_t internal_file_len; if ((resource = phar_parse_url(wrapper, url, "r", flags|PHP_STREAM_URL_STAT_QUIET)) == NULL) { @@ -583,7 +581,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f return FAILURE; } - host_len = ZSTR_LEN(resource->host); + size_t host_len = ZSTR_LEN(resource->host); phar_request_initialize(); internal_file = ZSTR_VAL(resource->path) + 1; /* strip leading "/" */ @@ -674,7 +672,6 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int int internal_file_len; phar_entry_data *idata; phar_archive_data *pphar; - uint32_t host_len; if ((resource = phar_parse_url(wrapper, url, "rb", options)) == NULL) { php_stream_wrapper_log_error(wrapper, options, "phar error: unlink failed"); @@ -694,7 +691,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int return 0; } - host_len = ZSTR_LEN(resource->host); + size_t host_len = ZSTR_LEN(resource->host); phar_request_initialize(); pphar = zend_hash_find_ptr(&(PHAR_G(phar_fname_map)), resource->host); @@ -747,7 +744,6 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from char *error; phar_archive_data *phar, *pfrom, *pto; phar_entry_info *entry; - uint32_t host_len; int is_dir = 0; int is_modified = 0; @@ -823,7 +819,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from return 0; } - host_len = ZSTR_LEN(resource_from->host); + size_t host_len = ZSTR_LEN(resource_from->host); if (SUCCESS != phar_get_archive(&phar, ZSTR_VAL(resource_from->host), host_len, NULL, 0, &error)) { php_url_free(resource_from); @@ -893,8 +889,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from Bucket *b; zend_string *str_key; zend_string *new_str_key; - uint32_t from_len = ZSTR_LEN(resource_from->path) - 1; - uint32_t to_len = ZSTR_LEN(resource_to->path) - 1; + size_t from_len = ZSTR_LEN(resource_from->path) - 1; + size_t to_len = ZSTR_LEN(resource_to->path) - 1; ZEND_HASH_MAP_FOREACH_BUCKET(&phar->manifest, b) { str_key = b->key; diff --git a/ext/phar/stream.h b/ext/phar/stream.h index 732da3a0b3f2..ce75b70dcba0 100644 --- a/ext/phar/stream.h +++ b/ext/phar/stream.h @@ -18,6 +18,7 @@ */ BEGIN_EXTERN_C() +#include "ext/standard/url.h" php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options); void phar_entry_remove(phar_entry_data *idata, char **error); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 0b1de03c33f7..44a8e127e233 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -18,6 +18,7 @@ */ #include "phar_internal.h" +#include "ext/standard/php_string.h" /* For php_stristr() */ static uint32_t phar_tar_number(const char *buf, size_t len) /* {{{ */ { @@ -62,10 +63,10 @@ static uint32_t phar_tar_number(const char *buf, size_t len) /* {{{ */ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -static int phar_tar_octal(char *buf, uint32_t val, int len) /* {{{ */ +static zend_result phar_tar_octal(char *buf, uint32_t val, size_t len) /* {{{ */ { char *p = buf; - int s = len; + size_t s = len; p += len; /* Start at the end and work backwards. */ while (s-- > 0) { @@ -73,12 +74,14 @@ static int phar_tar_octal(char *buf, uint32_t val, int len) /* {{{ */ val >>= 3; } - if (val == 0) + if (val == 0) { return SUCCESS; + } /* If it overflowed, fill field with max value. */ - while (len-- > 0) + while (len-- > 0) { *p++ = '7'; + } return FAILURE; } @@ -97,37 +100,37 @@ static uint32_t phar_tar_checksum(char *buf, size_t len) /* {{{ */ } /* }}} */ -int phar_is_tar(char *buf, char *fname) /* {{{ */ +bool phar_is_tar(char *buf, char *fname) /* {{{ */ { tar_header *header = (tar_header *) buf; uint32_t checksum = phar_tar_number(header->checksum, sizeof(header->checksum)); - uint32_t ret; + bool is_tar; char save[sizeof(header->checksum)], *bname; /* assume that the first filename in a tar won't begin with checksum, sizeof(header->checksum)); memset(header->checksum, ' ', sizeof(header->checksum)); - ret = (checksum == phar_tar_checksum(buf, 512)); + is_tar = (checksum == phar_tar_checksum(buf, 512)); memcpy(header->checksum, save, sizeof(header->checksum)); if ((bname = strrchr(fname, PHP_DIR_SEPARATOR))) { fname = bname; } - if (!ret && (bname = strstr(fname, ".tar")) && (bname[4] == '\0' || bname[4] == '.')) { + if (!is_tar && (bname = strstr(fname, ".tar")) && (bname[4] == '\0' || bname[4] == '.')) { /* probably a corrupted tar - so we will pretend it is one */ - return 1; + return true; } - return ret; + return is_tar; } /* }}} */ -int phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; - int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error); + zend_result ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error); if (FAILURE == ret) { return FAILURE; @@ -157,7 +160,7 @@ int phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t a } /* }}} */ -static int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp) /* {{{ */ +static zend_result phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp) /* {{{ */ { char *metadata; size_t save = php_stream_tell(fp), read; @@ -199,7 +202,7 @@ static int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp) /* } /* }}} */ -int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, int is_data, uint32_t compression, char **error) /* {{{ */ +zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */ { char buf[512], *actual_alias = NULL, *p; phar_entry_info entry = {0}; @@ -699,8 +702,8 @@ int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alia struct _phar_pass_tar_info { php_stream *old; php_stream *new; - int free_fp; - int free_ufp; + bool free_fp; + bool free_ufp; char **error; }; @@ -863,7 +866,7 @@ static int phar_tar_writeheaders(zval *zv, void *argument) /* {{{ */ } /* }}} */ -int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry_info *entry, char **error) /* {{{ */ +static int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry_info *entry, char **error) /* {{{ */ { /* Copy the metadata from tracker to the new entry being written out to temporary files */ const zend_string *serialized_str; diff --git a/ext/phar/util.c b/ext/phar/util.c index 3a366216650a..e49e15aee9cc 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -19,7 +19,10 @@ */ #include "phar_internal.h" +#include "php_phar.h" +#include "ext/hash/php_hash.h" /* Needed for PHP_HASH_API in ext/hash/php_hash_sha.h */ #include "ext/hash/php_hash_sha.h" +#include "ext/standard/md5.h" #ifdef PHAR_HAVE_OPENSSL /* OpenSSL includes */ @@ -82,6 +85,14 @@ phar_entry_info *phar_get_link_source(phar_entry_info *entry) /* {{{ */ } /* }}} */ +static php_stream *phar_get_entrypufp(const phar_entry_info *entry) +{ + if (!entry->is_persistent) { + return entry->phar->ufp; + } + return PHAR_G(cached_fp)[entry->phar->phar_pos].ufp; +} + /* retrieve a phar_entry_info's current file pointer for reading contents */ php_stream *phar_get_efp(phar_entry_info *entry, int follow_links) /* {{{ */ { @@ -113,6 +124,19 @@ php_stream *phar_get_efp(phar_entry_info *entry, int follow_links) /* {{{ */ } /* }}} */ +static zend_off_t phar_get_fp_offset(const phar_entry_info *entry) +{ + if (!entry->is_persistent) { + return entry->offset; + } + if (PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].fp_type == PHAR_FP) { + if (!PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].offset) { + PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].offset = entry->offset; + } + } + return PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos].offset; +} + int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links) /* {{{ */ { php_stream *fp = phar_get_efp(entry, follow_links); @@ -163,7 +187,7 @@ int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_of /* }}} */ /* mount an absolute path or uri to a path internal to the phar archive */ -int phar_mount_entry(phar_archive_data *phar, char *filename, size_t filename_len, char *path, size_t path_len) /* {{{ */ +zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t filename_len, char *path, size_t path_len) /* {{{ */ { phar_entry_info entry = {0}; php_stream_statbuf ssb; @@ -340,6 +364,105 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data } /* }}} */ +static zend_result phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */ +{ + if (entry->fp_type == PHAR_MOD) { + /* already newly created, truncate */ + php_stream_truncate_set_size(entry->fp, 0); + + entry->old_flags = entry->flags; + entry->is_modified = 1; + phar->is_modified = 1; + /* reset file size */ + entry->uncompressed_filesize = 0; + entry->compressed_filesize = 0; + entry->crc32 = 0; + entry->flags = PHAR_ENT_PERM_DEF_FILE; + entry->fp_type = PHAR_MOD; + entry->offset = 0; + return SUCCESS; + } + + if (error) { + *error = NULL; + } + + /* open a new temp file for writing */ + if (entry->link) { + efree(entry->link); + entry->link = NULL; + entry->tar_type = (entry->is_tar ? TAR_FILE : '\0'); + } + + entry->fp = php_stream_fopen_tmpfile(); + + if (!entry->fp) { + if (error) { + spprintf(error, 0, "phar error: unable to create temporary file"); + } + return FAILURE; + } + + entry->old_flags = entry->flags; + entry->is_modified = 1; + phar->is_modified = 1; + /* reset file size */ + entry->uncompressed_filesize = 0; + entry->compressed_filesize = 0; + entry->crc32 = 0; + entry->flags = PHAR_ENT_PERM_DEF_FILE; + entry->fp_type = PHAR_MOD; + entry->offset = 0; + return SUCCESS; +} +/* }}} */ + +static zend_result phar_separate_entry_fp(phar_entry_info *entry, char **error) /* {{{ */ +{ + php_stream *fp; + phar_entry_info *link; + + if (FAILURE == phar_open_entry_fp(entry, error, 1)) { + return FAILURE; + } + + if (entry->fp_type == PHAR_MOD) { + return SUCCESS; + } + + fp = php_stream_fopen_tmpfile(); + if (fp == NULL) { + spprintf(error, 0, "phar error: unable to create temporary file"); + return FAILURE; + } + phar_seek_efp(entry, 0, SEEK_SET, 0, 1); + link = phar_get_link_source(entry); + + if (!link) { + link = entry; + } + + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) { + if (error) { + spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname); + } + return FAILURE; + } + + if (entry->link) { + efree(entry->link); + entry->link = NULL; + entry->tar_type = (entry->is_tar ? TAR_FILE : '\0'); + } + + entry->offset = 0; + entry->fp = fp; + entry->fp_type = PHAR_MOD; + entry->is_modified = 1; + return SUCCESS; +} +/* }}} */ + /** * Retrieve a copy of the file information on a single file within a phar, or null. * This also transfers the open file pointer, if any, to the entry. @@ -348,14 +471,14 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data * appended, truncated, or read. For read, if the entry is marked unmodified, it is * assumed that the file pointer, if present, is opened for reading */ -int phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */ +zend_result phar_get_entry_data(phar_entry_data **ret, char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry; - int for_write = mode[0] != 'r' || mode[1] == '+'; - int for_append = mode[0] == 'a'; - int for_create = mode[0] != 'r'; - int for_trunc = mode[0] == 'w'; + bool for_write = mode[0] != 'r' || mode[1] == '+'; + bool for_append = mode[0] == 'a'; + bool for_create = mode[0] != 'r'; + bool for_trunc = mode[0] == 'w'; if (!ret) { return FAILURE; @@ -616,8 +739,18 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch } /* }}} */ +static inline void phar_set_pharfp(phar_archive_data *phar, php_stream *fp) +{ + if (!phar->is_persistent) { + phar->fp = fp; + return; + } + + PHAR_G(cached_fp)[phar->phar_pos].fp = fp; +} + /* initialize a phar_archive_data's read-only fp for existing phar data */ -int phar_open_archive_fp(phar_archive_data *phar) /* {{{ */ +zend_result phar_open_archive_fp(phar_archive_data *phar) /* {{{ */ { if (phar_get_pharfp(phar)) { return SUCCESS; @@ -638,7 +771,7 @@ int phar_open_archive_fp(phar_archive_data *phar) /* {{{ */ /* }}} */ /* copy file data from an existing to a new phar_entry_info that is not in the manifest */ -int phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error) /* {{{ */ +zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error) /* {{{ */ { phar_entry_info *link; @@ -680,9 +813,33 @@ int phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **er } /* }}} */ +static void phar_set_entrypufp(const phar_entry_info *entry, php_stream *fp) +{ + if (!entry->phar->is_persistent) { + entry->phar->ufp = fp; + return; + } + + PHAR_G(cached_fp)[entry->phar->phar_pos].ufp = fp; +} + +static void phar_set_fp_type(phar_entry_info *entry, enum phar_fp_type type, zend_off_t offset) +{ + phar_entry_fp_info *data; + + if (!entry->is_persistent) { + entry->fp_type = type; + entry->offset = offset; + return; + } + data = &(PHAR_G(cached_fp)[entry->phar->phar_pos].manifest[entry->manifest_pos]); + data->fp_type = type; + data->offset = offset; +} + /* open and decompress a compressed phar entry */ -int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links) /* {{{ */ +zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links) /* {{{ */ { php_stream_filter *filter; phar_archive_data *phar = entry->phar; @@ -798,105 +955,6 @@ int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links) / } /* }}} */ -int phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */ -{ - if (entry->fp_type == PHAR_MOD) { - /* already newly created, truncate */ - php_stream_truncate_set_size(entry->fp, 0); - - entry->old_flags = entry->flags; - entry->is_modified = 1; - phar->is_modified = 1; - /* reset file size */ - entry->uncompressed_filesize = 0; - entry->compressed_filesize = 0; - entry->crc32 = 0; - entry->flags = PHAR_ENT_PERM_DEF_FILE; - entry->fp_type = PHAR_MOD; - entry->offset = 0; - return SUCCESS; - } - - if (error) { - *error = NULL; - } - - /* open a new temp file for writing */ - if (entry->link) { - efree(entry->link); - entry->link = NULL; - entry->tar_type = (entry->is_tar ? TAR_FILE : '\0'); - } - - entry->fp = php_stream_fopen_tmpfile(); - - if (!entry->fp) { - if (error) { - spprintf(error, 0, "phar error: unable to create temporary file"); - } - return FAILURE; - } - - entry->old_flags = entry->flags; - entry->is_modified = 1; - phar->is_modified = 1; - /* reset file size */ - entry->uncompressed_filesize = 0; - entry->compressed_filesize = 0; - entry->crc32 = 0; - entry->flags = PHAR_ENT_PERM_DEF_FILE; - entry->fp_type = PHAR_MOD; - entry->offset = 0; - return SUCCESS; -} -/* }}} */ - -int phar_separate_entry_fp(phar_entry_info *entry, char **error) /* {{{ */ -{ - php_stream *fp; - phar_entry_info *link; - - if (FAILURE == phar_open_entry_fp(entry, error, 1)) { - return FAILURE; - } - - if (entry->fp_type == PHAR_MOD) { - return SUCCESS; - } - - fp = php_stream_fopen_tmpfile(); - if (fp == NULL) { - spprintf(error, 0, "phar error: unable to create temporary file"); - return FAILURE; - } - phar_seek_efp(entry, 0, SEEK_SET, 0, 1); - link = phar_get_link_source(entry); - - if (!link) { - link = entry; - } - - if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) { - if (error) { - spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname); - } - return FAILURE; - } - - if (entry->link) { - efree(entry->link); - entry->link = NULL; - entry->tar_type = (entry->is_tar ? TAR_FILE : '\0'); - } - - entry->offset = 0; - entry->fp = fp; - entry->fp_type = PHAR_MOD; - entry->is_modified = 1; - return SUCCESS; -} -/* }}} */ - /** * helper function to open an internal file's fp just-in-time */ @@ -917,7 +975,7 @@ phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, } /* }}} */ -PHP_PHAR_API int phar_resolve_alias(char *alias, size_t alias_len, char **filename, size_t *filename_len) /* {{{ */ { +PHP_PHAR_API zend_result phar_resolve_alias(char *alias, size_t alias_len, char **filename, size_t *filename_len) /* {{{ */ { phar_archive_data *fd_ptr; if (HT_IS_INITIALIZED(&PHAR_G(phar_alias_map)) && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) { @@ -929,7 +987,7 @@ PHP_PHAR_API int phar_resolve_alias(char *alias, size_t alias_len, char **filena } /* }}} */ -int phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len) /* {{{ */ +zend_result phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len) /* {{{ */ { if (phar->refcount || phar->is_persistent) { return FAILURE; @@ -952,7 +1010,7 @@ int phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len) /* { * Looks up a phar archive in the filename map, connecting it to the alias * (if any) or returns null */ -int phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error) /* {{{ */ +zend_result phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error) /* {{{ */ { phar_archive_data *fd, *fd_ptr; char *my_realpath, *save; @@ -1482,7 +1540,7 @@ static int phar_call_openssl_signverify(int is_sign, php_stream *fp, zend_off_t /* }}} */ #endif /* #ifndef PHAR_HAVE_OPENSSL */ -int phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, char *fname, char **signature, size_t *signature_len, char **error) /* {{{ */ +zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, char *fname, char **signature, size_t *signature_len, char **error) /* {{{ */ { size_t read_size, len; zend_off_t read_len; @@ -1796,7 +1854,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, } /* }}} */ -int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */ +zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */ { unsigned char buf[1024]; size_t sig_len; @@ -2079,7 +2137,7 @@ static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */ } /* }}} */ -int phar_copy_on_write(phar_archive_data **pphar) /* {{{ */ +zend_result phar_copy_on_write(phar_archive_data **pphar) /* {{{ */ { zval zv, *pzv; phar_archive_data *newpphar; diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 9faf6054aff0..70cdfc9cc1b5 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -17,6 +17,8 @@ */ #include "phar_internal.h" +#include "ext/standard/crc32.h" +#include "ext/standard/php_string.h" /* For php_stristr() */ #define PHAR_GET_16(var) ((uint16_t)((((uint16_t)var[0]) & 0xff) | \ (((uint16_t)var[1]) & 0xff) << 8))