diff --git a/NEWS b/NEWS index 18d12d02dbbe..d26148877670 100644 --- a/NEWS +++ b/NEWS @@ -197,4 +197,8 @@ PHP NEWS . Added ZipArchive::openString() method. (Tim Starling, Soner Sayakci, Ghaith Olabi) +- Zlib: + . deflate_init() now raises a TypeError when the value for option + "strategy" is not of type int. (Weilin Du) + <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> diff --git a/UPGRADING b/UPGRADING index f24ea681be2e..6c6115ebcc84 100644 --- a/UPGRADING +++ b/UPGRADING @@ -101,6 +101,10 @@ PHP 8.6 UPGRADE NOTES files argument if one or more of the entries is not a string. +- Zlib: + . deflate_init() now raises a TypeError when the value for option + "strategy" is not of type int. + ======================================== 2. New Features ======================================== diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 1d53df7e4a33..10c71d19a563 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -91,6 +91,7 @@ PHP 8.6 INTERNALS UPGRADE NOTES . Functions using zend_forbid_dynamic_call() *must* be flagged with ZEND_ACC2_FORBID_DYN_CALLS (@forbid-dynamic-calls in stubs). In debug builds, failing to include that flag will lead to assertion failures. + . The ZEND_RESULT_CODE type has been removed. Use zend_result directly. ======================== 2. Build system changes diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 78cc114223d0..96433e16e713 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5465,7 +5465,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type) } zval_ptr_dtor(&name_node.u.constant); - ZVAL_NEW_STR(&name_node.u.constant, lcname); + ZVAL_STR(&name_node.u.constant, lcname); opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node); opline->result.num = zend_alloc_cache_slot(); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index dc6ea2c800ee..30d77da67323 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -54,12 +54,10 @@ typedef unsigned char zend_uchar; -typedef enum { +typedef enum zend_result { SUCCESS = 0, FAILURE = -1, /* this MUST stay a negative number, or it may affect functions! */ -} ZEND_RESULT_CODE; - -typedef ZEND_RESULT_CODE zend_result; +} zend_result; /* This constant is deprecated, use SIZE_MAX instead */ #define ZEND_SIZE_MAX SIZE_MAX diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 05655aa41515..2ab799ab8c83 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -504,15 +504,20 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al phar_unixify_path_separators(fname, fname_len); } #endif - if (SUCCESS == phar_get_archive(&phar, fname, fname_len, alias, alias_len, error) - && ((alias && zend_string_equals_cstr(phar->fname, fname, fname_len)) || !alias) - ) { + zend_result archive_retrieved = phar_get_archive(&phar, fname, fname_len, alias, alias_len, error); + /* logic is as follows: + - If no alias was passed in, then it can match either and be valid + - If an explicit alias was requested, ensure the filename passed in matches the phar's filename. + */ + bool process_phar = SUCCESS == archive_retrieved && (!alias || zend_string_equals_cstr(phar->fname, fname, fname_len)); #ifdef PHP_WIN32 - if (fname != save_fname) { - free_alloca(fname, fname_use_heap); - fname = save_fname; - } + if (fname != save_fname) { + free_alloca(fname, fname_use_heap); + fname = save_fname; + } #endif + + if (process_phar) { /* logic above is as follows: If an explicit alias was requested, ensure the filename passed in matches the phar's filename. @@ -537,12 +542,6 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al return SUCCESS; } else { -#ifdef PHP_WIN32 - if (fname != save_fname) { - free_alloca(fname, fname_use_heap); - fname = save_fname; - } -#endif if (pphar) { *pphar = NULL; } @@ -1304,7 +1303,7 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname /** * Create or open a phar for writing */ -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) 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_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, 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; @@ -1316,31 +1315,31 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(ch *error = NULL; /* first try to open an existing file */ - if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, true) == SUCCESS) { + if (phar_detect_phar_fname_ext(ZSTR_VAL(fname), ZSTR_LEN(fname), &ext_str, &ext_len, !is_data, 0, true) == SUCCESS) { goto check_file; } /* next try to create a new file */ - if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, true)) { + if (FAILURE == phar_detect_phar_fname_ext(ZSTR_VAL(fname), ZSTR_LEN(fname), &ext_str, &ext_len, !is_data, 1, true)) { if (ext_len == -2) { - spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", fname); + spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", ZSTR_VAL(fname)); } else { - spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", fname); + spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", ZSTR_VAL(fname)); } return FAILURE; } check_file: - if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, test, &my_error) == SUCCESS) { + if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, is_data, options, test, &my_error) == SUCCESS) { *pphar = *test; if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) { - spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname); + spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", ZSTR_VAL(fname)); return FAILURE; } if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) { if (!zend_hash_str_exists(&((*test)->manifest), ZEND_STRL(".phar/stub.php"))) { - spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname); + spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", ZSTR_VAL(fname)); return FAILURE; } } @@ -1356,40 +1355,40 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_filename(ch if (ext_len > 3 && (z = memchr(ext_str, 'z', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ip", 2)) { /* assume zip-based phar */ - return phar_open_or_create_zip(fname, fname_len, alias, alias_len, is_data, options, pphar, error); + return phar_open_or_create_zip(fname, alias, alias_len, is_data, options, pphar, error); } if (ext_len > 3 && (z = memchr(ext_str, 't', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ar", 2)) { /* assume tar-based phar */ - return phar_open_or_create_tar(fname, fname_len, alias, alias_len, is_data, options, pphar, error); + return phar_open_or_create_tar(fname, alias, alias_len, is_data, options, pphar, error); } - return phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, pphar, error); + return phar_create_or_parse_filename(fname, alias, alias_len, is_data, options, pphar, 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_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) 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_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { php_stream *fp; zend_string *actual = NULL; + zend_string *save_fname = fname; char *p; - if (php_check_open_basedir(fname)) { + if (php_check_open_basedir(ZSTR_VAL(fname))) { return FAILURE; } /* first open readonly so it won't be created if not present */ - fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual); + fp = php_stream_open_wrapper(ZSTR_VAL(fname), "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual); if (actual) { - fname = ZSTR_VAL(actual); - fname_len = ZSTR_LEN(actual); + fname = actual; } if (fp) { - if (phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error) == SUCCESS) { + if (phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, options, pphar, error) == SUCCESS) { if ((*pphar)->is_data || !PHAR_G(readonly)) { (*pphar)->is_writeable = 1; } @@ -1408,11 +1407,12 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c if (actual) { zend_string_release_ex(actual, 0); + fname = save_fname; } if (PHAR_G(readonly) && !is_data) { if (options & REPORT_ERRORS) { - spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", fname); + spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", ZSTR_VAL(fname)); } return FAILURE; } @@ -1420,7 +1420,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c /* set up our manifest */ phar_archive_data *mydata = ecalloc(1, sizeof(phar_archive_data)); /* TODO: prevent reallocation via a new expand_filepath() API? */ - char *new_fname = expand_filepath(fname, NULL); + char *new_fname = expand_filepath(ZSTR_VAL(fname), NULL); if (new_fname == NULL) { efree(mydata); return FAILURE; @@ -1485,7 +1485,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c if (alias_len && alias) { if (NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata)) { if (options & REPORT_ERRORS) { - spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias); + spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", ZSTR_VAL(fname), alias); } zend_hash_del(&(PHAR_G(phar_fname_map)), mydata->fname); diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 4afe485ddf76..36fa2b543501 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -407,8 +407,8 @@ void phar_destroy_phar_data(phar_archive_data *phar); ZEND_ATTRIBUTE_NONNULL 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_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) 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_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) 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_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); zend_result phar_free_alias(const phar_archive_data *phar); zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error); @@ -446,12 +446,12 @@ zend_result phar_copy_on_write(phar_archive_data **pphar); /* tar functions in tar.c */ bool phar_is_tar(const char *buf, const char *fname); zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_tar(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_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error); /* zip functions in zip.c */ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_zip(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_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error); #ifdef PHAR_MAIN @@ -466,8 +466,8 @@ 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, bool security); phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, bool security); -ZEND_ATTRIBUTE_NONNULL 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, bool security, uint32_t timestamp); -ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, const char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security); +ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security, uint32_t timestamp); +ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, const zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security); 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); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index d356c61ea5d6..c07ff93b951f 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -967,16 +967,17 @@ PHP_METHOD(Phar, mapPhar) /* {{{ Loads any phar archive with an alias */ PHP_METHOD(Phar, loadPhar) { - char *fname, *alias = NULL, *error; - size_t fname_len, alias_len = 0; + zend_string *fname; + char *alias = NULL, *error; + size_t alias_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!", &fname, &fname_len, &alias, &alias_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|s!", &fname, &alias, &alias_len) == FAILURE) { RETURN_THROWS(); } phar_request_initialize(); - RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error) == SUCCESS); + RETVAL_BOOL(phar_open_from_filename(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, REPORT_ERRORS, NULL, &error) == SUCCESS); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); @@ -1081,8 +1082,9 @@ static const spl_other_handler phar_spl_foreign_handler = { */ PHP_METHOD(Phar, __construct) { - char *fname, *alias = NULL, *error, *save_fname; - size_t fname_len, alias_len = 0; + zend_string *fname; + char *alias = NULL, *error; + size_t alias_len = 0; bool is_data; zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS; zend_long format = 0; @@ -1095,11 +1097,11 @@ PHP_METHOD(Phar, __construct) is_data = instanceof_function(Z_OBJCE_P(ZEND_THIS), phar_ce_data); if (is_data) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ls!l", &fname, &flags, &alias, &alias_len, &format) == FAILURE) { RETURN_THROWS(); } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ls!", &fname, &flags, &alias, &alias_len) == FAILURE) { RETURN_THROWS(); } } @@ -1109,23 +1111,22 @@ PHP_METHOD(Phar, __construct) RETURN_THROWS(); } - save_fname = fname; zend_string *entry = NULL; /* phar_split_fname() will unixify the path */ - zend_string *arch = phar_split_fname(fname, fname_len, &entry, !is_data, 2); + zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &entry, !is_data, 2); if (arch) { /* use arch (the basename for the archive) for fname instead of fname */ /* this allows support for RecursiveDirectoryIterator of subdirectories */ - fname = ZSTR_VAL(arch); - fname_len = ZSTR_LEN(arch); + fname = arch; } - if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error) == FAILURE) { + zend_result phar_status = phar_open_or_create_filename(fname, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error); - if (arch && fname == ZSTR_VAL(arch) && fname != save_fname) { - zend_string_release_ex(arch, false); - fname = save_fname; - } + if (arch) { + zend_string_release_ex(arch, false); + } + + if (phar_status == FAILURE) { if (entry) { zend_string_release_ex(entry, false); @@ -1148,11 +1149,6 @@ PHP_METHOD(Phar, __construct) phar_data->is_tar = false; } - if (arch && fname == ZSTR_VAL(arch)) { - zend_string_release_ex(arch, false); - fname = save_fname; - } - if ((is_data && !phar_data->is_data) || (!is_data && phar_data->is_data)) { if (is_data) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, @@ -1346,7 +1342,7 @@ static zend_always_inline void phar_call_method_with_unwrap(zend_object *obj, co } /* This is the same as phar_get_or_create_entry_data(), but allows overriding metadata via SplFileInfo. */ -static phar_entry_data *phar_build_entry_data(char *fname, size_t fname_len, char *path, size_t path_len, char **error, zval *file_info) +static phar_entry_data *phar_build_entry_data(zend_string *fname, char *path, size_t path_len, char **error, zval *file_info) { uint32_t timestamp; @@ -1372,7 +1368,7 @@ static phar_entry_data *phar_build_entry_data(char *fname, size_t fname_len, cha timestamp = time(NULL); } - return phar_get_or_create_entry_data(fname, fname_len, path, path_len, "w+b", 0, error, true, timestamp); + return phar_get_or_create_entry_data(fname, path, path_len, "w+b", 0, error, true, timestamp); } static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ @@ -1635,7 +1631,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */ return ZEND_HASH_APPLY_KEEP; } - data = phar_build_entry_data(ZSTR_VAL(phar_obj->archive->fname), ZSTR_LEN(phar_obj->archive->fname), str_key, str_key_len, &error, value); + data = phar_build_entry_data(phar_obj->archive->fname, str_key, str_key_len, &error, value); if (!data) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s cannot be created: %s", str_key, error); efree(error); @@ -3597,7 +3593,7 @@ static void phar_add_file(phar_archive_data **pphar, zend_string *file_name, con } #endif - phar_entry_data *data = phar_get_or_create_entry_data(ZSTR_VAL((*pphar)->fname), ZSTR_LEN((*pphar)->fname), filename, filename_len, "w+b", 0, &error, true, time(NULL)); + phar_entry_data *data = phar_get_or_create_entry_data((*pphar)->fname, filename, filename_len, "w+b", 0, &error, true, time(NULL)); if (!data) { if (error) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created: %s", filename, error); @@ -3672,7 +3668,7 @@ static void phar_mkdir(phar_archive_data **pphar, zend_string *dir_name) char *error; phar_entry_data *data = phar_get_or_create_entry_data( - ZSTR_VAL((*pphar)->fname), ZSTR_LEN((*pphar)->fname), + (*pphar)->fname, ZSTR_VAL(dir_name), ZSTR_LEN(dir_name), "w+b", 2, &error, true, time(NULL) diff --git a/ext/phar/stream.c b/ext/phar/stream.c index a9c4dc98d7de..2a0bdf7e1acc 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -114,7 +114,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const php_url_free(resource); return NULL; } - if (phar_open_or_create_filename(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, 0, options, &phar, &error) == FAILURE) + if (phar_open_or_create_filename(resource->host, NULL, 0, 0, options, &phar, &error) == FAILURE) { if (error) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { @@ -189,7 +189,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha /* strip leading "/" */ internal_file = estrndup(ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1); if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) { - if (NULL == (idata = phar_get_or_create_entry_data(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, strlen(internal_file), mode, 0, &error, true, time(NULL)))) { + if (NULL == (idata = phar_get_or_create_entry_data(resource->host, internal_file, strlen(internal_file), mode, 0, &error, true, time(NULL)))) { if (error) { php_stream_wrapper_log_error(wrapper, options, "%s", error); efree(error); @@ -240,7 +240,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha return NULL; } if (phar->is_tar || phar->is_zip) { - if ((FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), ".phar/stub.php", sizeof(".phar/stub.php")-1, "r", 0, &error, false)) || !idata) { + if ((FAILURE == phar_get_entry_data(&idata, resource->host, ".phar/stub.php", sizeof(".phar/stub.php")-1, "r", 0, &error, false)) || !idata) { goto idata_error; } efree(internal_file); @@ -288,7 +288,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } } /* read-only access is allowed to magic files in .phar directory */ - if ((FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, strlen(internal_file), "r", 0, &error, false)) || !idata) { + if ((FAILURE == phar_get_entry_data(&idata, resource->host, internal_file, strlen(internal_file), "r", 0, &error, false)) || !idata) { idata_error: if (error) { php_stream_wrapper_log_error(wrapper, options, "%s", error); @@ -694,7 +694,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int /* need to copy to strip leading "/", will get touched again */ internal_file = estrndup(ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1); internal_file_len = ZSTR_LEN(resource->path) - 1; - if (FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), internal_file, internal_file_len, "r", 0, &error, true)) { + if (FAILURE == phar_get_entry_data(&idata, resource->host, internal_file, internal_file_len, "r", 0, &error, true)) { /* constraints of fp refcount were not met */ if (error) { php_stream_wrapper_log_error(wrapper, options, "unlink of \"%s\" failed: %s", url, error); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 7492fed85748..a7c02e352731 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -126,10 +126,10 @@ bool phar_is_tar(const char *buf, const char *fname) /* {{{ */ } /* }}} */ -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_tar(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_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; - zend_result 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, alias, alias_len, is_data, options, &phar, error); if (FAILURE == ret) { return FAILURE; @@ -150,7 +150,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_tar(char *f } /* we've reached here - the phar exists and is a regular phar */ - spprintf(error, 4096, "phar tar error: \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a tar-based phar", fname); + spprintf(error, 4096, "phar tar error: \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a tar-based phar", ZSTR_VAL(fname)); return FAILURE; } /* }}} */ diff --git a/ext/phar/util.c b/ext/phar/util.c index 136dae4f882d..efab7f9edab6 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -466,7 +466,7 @@ ZEND_ATTRIBUTE_NONNULL static zend_result phar_separate_entry_fp(phar_entry_info * 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 */ -ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, const char *fname, size_t fname_len, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, const zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry; @@ -478,17 +478,17 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co *ret = NULL; *error = NULL; - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 0, error)) { return FAILURE; } if (for_write && PHAR_G(readonly) && !phar->is_data) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, fname); + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, ZSTR_VAL(fname)); return FAILURE; } if (!path_len) { - spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" must not be empty", fname); + spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" must not be empty", ZSTR_VAL(fname)); return FAILURE; } really_get_entry: @@ -512,7 +512,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co if (for_write && phar->is_persistent) { if (FAILURE == phar_copy_on_write(&phar)) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, could not make cached phar writeable", path, fname); + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, could not make cached phar writeable", path, ZSTR_VAL(fname)); return FAILURE; } else { goto really_get_entry; @@ -520,12 +520,12 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co } if (entry->is_modified && !for_write) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, fname); + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, ZSTR_VAL(fname)); return FAILURE; } if (entry->fp_refcount && for_write) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, fname); + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, ZSTR_VAL(fname)); return FAILURE; } @@ -611,7 +611,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co /** * Create a new dummy file slot within a writeable phar for a newly created file */ -ZEND_ATTRIBUTE_NONNULL 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, bool security, uint32_t timestamp) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security, uint32_t timestamp) /* {{{ */ { phar_archive_data *phar; phar_entry_info etemp; @@ -625,11 +625,11 @@ ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(char *fnam is_dir = (path_len && path[path_len - 1] == '/') ? 1 : 0; - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 0, error)) { return NULL; } - if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, allow_dir, error, security)) { + if (FAILURE == phar_get_entry_data(&ret, fname, path, path_len, mode, allow_dir, error, security)) { return NULL; } else if (ret) { return ret; @@ -641,7 +641,7 @@ ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(char *fnam } if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar)) { - spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be created, could not make cached phar writeable", path, fname); + spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be created, could not make cached phar writeable", path, ZSTR_VAL(fname)); return NULL; } diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 44d962dae39d..28e1a3d5641e 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -794,10 +794,10 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l /** * Create or open a zip-based phar for writing */ -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_zip(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_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; - zend_result 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, alias, alias_len, is_data, options, &phar, error); if (FAILURE == ret) { return FAILURE; @@ -818,7 +818,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_open_or_create_zip(char *f } /* we've reached here - the phar exists and is a regular phar */ - spprintf(error, 4096, "phar zip error: phar \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a zip-based phar", fname); + spprintf(error, 4096, "phar zip error: phar \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a zip-based phar", ZSTR_VAL(fname)); return FAILURE; } diff --git a/ext/random/php_random.h b/ext/random/php_random.h index df53ad3fc55e..7c17cd40790f 100644 --- a/ext/random/php_random.h +++ b/ext/random/php_random.h @@ -36,16 +36,6 @@ PHPAPI double php_combined_lcg(void); -typedef struct _php_random_fallback_seed_state php_random_fallback_seed_state; - -PHPAPI uint64_t php_random_generate_fallback_seed(void); -PHPAPI uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_state *state); - -static inline zend_long GENERATE_SEED(void) -{ - return (zend_long)php_random_generate_fallback_seed(); -} - # define PHP_MT_RAND_MAX ((zend_long) (0x7FFFFFFF)) /* (1<<31) - 1 */ enum php_random_mt19937_mode { @@ -60,31 +50,31 @@ PHPAPI uint32_t php_mt_rand(void); PHPAPI zend_long php_mt_rand_range(zend_long min, zend_long max); PHPAPI zend_long php_mt_rand_common(zend_long min, zend_long max); -typedef struct _php_random_status_state_mt19937 { +typedef struct php_random_status_state_mt19937 { uint32_t count; enum php_random_mt19937_mode mode; uint32_t state[624]; } php_random_status_state_mt19937; -typedef struct _php_random_status_state_pcgoneseq128xslrr64 { +typedef struct php_random_status_state_pcgoneseq128xslrr64 { php_random_uint128_t state; } php_random_status_state_pcgoneseq128xslrr64; -typedef struct _php_random_status_state_xoshiro256starstar { +typedef struct php_random_status_state_xoshiro256starstar { uint64_t state[4]; } php_random_status_state_xoshiro256starstar; -typedef struct _php_random_status_state_user { +typedef struct php_random_status_state_user { zend_object *object; zend_function *generate_method; } php_random_status_state_user; -typedef struct _php_random_result { +typedef struct php_random_result { uint64_t result; size_t size; } php_random_result; -typedef struct _php_random_algo { +typedef struct php_random_algo { const size_t state_size; php_random_result (*generate)(void *state); zend_long (*range)(void *state, zend_long min, zend_long max); @@ -92,12 +82,12 @@ typedef struct _php_random_algo { bool (*unserialize)(void *state, HashTable *data); } php_random_algo; -typedef struct _php_random_algo_with_state { +typedef struct php_random_algo_with_state { const php_random_algo *algo; void *state; } php_random_algo_with_state; -typedef struct _php_random_fallback_seed_state { +typedef struct php_random_fallback_seed_state { bool initialized; unsigned char seed[20]; } php_random_fallback_seed_state; @@ -108,12 +98,12 @@ extern PHPAPI const php_random_algo php_random_algo_xoshiro256starstar; extern PHPAPI const php_random_algo php_random_algo_secure; extern PHPAPI const php_random_algo php_random_algo_user; -typedef struct _php_random_engine { +typedef struct php_random_engine { php_random_algo_with_state engine; zend_object std; } php_random_engine; -typedef struct _php_random_randomizer { +typedef struct php_random_randomizer { php_random_algo_with_state engine; bool is_userland_algo; zend_object std; @@ -147,6 +137,14 @@ static inline php_random_randomizer *php_random_randomizer_from_obj(zend_object # define Z_RANDOM_RANDOMIZER_P(zval) php_random_randomizer_from_obj(Z_OBJ_P(zval)); +PHPAPI uint64_t php_random_generate_fallback_seed(void); +PHPAPI uint64_t php_random_generate_fallback_seed_ex(php_random_fallback_seed_state *state); + +static inline zend_long GENERATE_SEED(void) +{ + return (zend_long)php_random_generate_fallback_seed(); +} + PHPAPI void *php_random_status_alloc(const php_random_algo *algo, const bool persistent); PHPAPI void *php_random_status_copy(const php_random_algo *algo, void *old_status, void *new_status); PHPAPI void php_random_status_free(void *status, const bool persistent); diff --git a/ext/random/php_random_uint128.h b/ext/random/php_random_uint128.h index 22c0444e5094..25d2677da436 100644 --- a/ext/random/php_random_uint128.h +++ b/ext/random/php_random_uint128.h @@ -21,7 +21,7 @@ # include # if !defined(__SIZEOF_INT128__) || defined(PHP_RANDOM_FORCE_EMULATE_128) -typedef struct _php_random_uint128_t { +typedef struct php_random_uint128_t { uint64_t hi; uint64_t lo; } php_random_uint128_t; diff --git a/ext/random/php_random_zend_utils.h b/ext/random/php_random_zend_utils.h index 5feba450f109..56718e5c214b 100644 --- a/ext/random/php_random_zend_utils.h +++ b/ext/random/php_random_zend_utils.h @@ -20,7 +20,7 @@ # include "php_random.h" # include "zend.h" -typedef struct _php_random_bytes_insecure_state_for_zend { +typedef struct php_random_bytes_insecure_state_for_zend { bool initialized; php_random_status_state_xoshiro256starstar xoshiro256starstar_state; } php_random_bytes_insecure_state_for_zend; diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 1468cec6ccf3..89af25dd9d35 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -2099,7 +2099,11 @@ PHP_METHOD(SplFileObject, fgets) spl_filesystem_file_free_line(intern); intern->u.file.current_line_num++; } else { - if (spl_filesystem_file_read_ex(intern, /* silent */ false, /* line_add */ 1, /* csv */ false) == FAILURE) { + if (spl_filesystem_file_read_ex(intern, /* silent */ true, /* line_add */ 1, /* csv */ false) == FAILURE) { + if (php_stream_eof(intern->u.file.stream)) { + RETURN_EMPTY_STRING(); + } + spl_filesystem_file_cannot_read(intern); RETURN_THROWS(); } RETVAL_STR_COPY(intern->u.file.current_line); diff --git a/ext/spl/tests/SplFileObject/gh21742.phpt b/ext/spl/tests/SplFileObject/gh21742.phpt new file mode 100644 index 000000000000..7ea60b53915a --- /dev/null +++ b/ext/spl/tests/SplFileObject/gh21742.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-21742 (SplFileObject::fgets() throws at EOF in while (!$spl->eof()) loop) +--FILE-- +eof()) { + echo $spl->fgets(); +} +echo "clean exit\n"; + +$empty = tempnam(sys_get_temp_dir(), 'spl'); +file_put_contents($empty, ''); +$spl2 = new SplFileObject($empty, 'r'); +$iter = 0; +while (!$spl2->eof()) { + $iter++; + $spl2->fgets(); + if ($iter > 3) break; +} +echo "empty-file iters=$iter\n"; + +unlink($file); +unlink($empty); +?> +--EXPECT-- +Line 0 +Line 1 +Line 2 +Line 3 +Line 4 +clean exit +empty-file iters=1 diff --git a/ext/zlib/tests/deflate_init_strategy_type_error.phpt b/ext/zlib/tests/deflate_init_strategy_type_error.phpt new file mode 100644 index 000000000000..0227d1bf6c29 --- /dev/null +++ b/ext/zlib/tests/deflate_init_strategy_type_error.phpt @@ -0,0 +1,16 @@ +--TEST-- +deflate_init(): strategy option type validation +--EXTENSIONS-- +zlib +--FILE-- + []]); +} catch (TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +deflate_init(): Argument #2 ($options) the value for option "strategy" must be of type int, array given diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index dbbaf1a24157..115eedbc894a 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -1115,8 +1115,14 @@ PHP_FUNCTION(deflate_init) } if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("strategy"))) != NULL) { + bool failed = false; + ZVAL_DEINDIRECT(option_buffer); - strategy = zval_get_long(option_buffer); + strategy = zval_try_get_long(option_buffer, &failed); + if (UNEXPECTED(failed)) { + zend_argument_type_error(2, "the value for option \"strategy\" must be of type int, %s given", zend_zval_value_name(option_buffer)); + RETURN_THROWS(); + } } switch (strategy) { case Z_FILTERED: