Commit 4f3c28aaac7 for php.net
commit 4f3c28aaac7ab4e5e66e7ef9018600d648ef29d2
Author: Niels Dossche <7771979+ndossche@users.noreply.github.com>
Date: Mon Dec 22 02:51:31 2025 -0800
phar: Simplify phar_open_archive_fp() (#20753)
By returning the stream directly, we avoid calling some helpers
functions and it becomes more clear on what stream the code actually
acts upon.
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index a4464444a02..b57f5596b37 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -2310,15 +2310,16 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata,
/* verify local file header */
phar_zip_file_header local;
phar_zip_data_desc desc;
+ php_stream *stream = phar_open_archive_fp(idata->phar);
- if (SUCCESS != phar_open_archive_fp(idata->phar)) {
+ if (!stream) {
spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"",
idata->phar->fname, ZSTR_VAL(entry->filename));
return FAILURE;
}
- php_stream_seek(phar_get_entrypfp(idata->internal_file), entry->header_offset, SEEK_SET);
+ php_stream_seek(stream, entry->header_offset, SEEK_SET);
- if (sizeof(local) != php_stream_read(phar_get_entrypfp(idata->internal_file), (char *) &local, sizeof(local))) {
+ if (sizeof(local) != php_stream_read(stream, (char *) &local, sizeof(local))) {
spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")",
idata->phar->fname, ZSTR_VAL(entry->filename));
return FAILURE;
@@ -2326,12 +2327,12 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata,
/* check for data descriptor */
if (((PHAR_ZIP_16(local.flags)) & 0x8) == 0x8) {
- php_stream_seek(phar_get_entrypfp(idata->internal_file),
+ php_stream_seek(stream,
entry->header_offset + sizeof(local) +
PHAR_ZIP_16(local.filename_len) +
PHAR_ZIP_16(local.extra_len) +
entry->compressed_filesize, SEEK_SET);
- if (sizeof(desc) != php_stream_read(phar_get_entrypfp(idata->internal_file),
+ if (sizeof(desc) != php_stream_read(stream,
(char *) &desc, sizeof(desc))) {
spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")",
idata->phar->fname, ZSTR_VAL(entry->filename));
diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h
index abdbb9a9816..5ed213fb03e 100644
--- a/ext/phar/phar_internal.h
+++ b/ext/phar/phar_internal.h
@@ -440,7 +440,7 @@ php_stream *phar_get_efp(phar_entry_info *entry, bool follow_links);
ZEND_ATTRIBUTE_NONNULL zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error);
ZEND_ATTRIBUTE_NONNULL zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, bool follow_links);
phar_entry_info *phar_get_link_source(phar_entry_info *entry);
-zend_result phar_open_archive_fp(phar_archive_data *phar);
+php_stream *phar_open_archive_fp(phar_archive_data *phar);
zend_result phar_copy_on_write(phar_archive_data **pphar);
/* tar functions in tar.c */
diff --git a/ext/phar/stream.c b/ext/phar/stream.c
index 08da1847cd9..4bd1e85666b 100644
--- a/ext/phar/stream.c
+++ b/ext/phar/stream.c
@@ -254,13 +254,13 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha
} else {
php_stream *stream = phar_get_pharfp(phar);
if (stream == NULL) {
- if (UNEXPECTED(FAILURE == phar_open_archive_fp(phar))) {
+ stream = phar_open_archive_fp(phar);
+ if (UNEXPECTED(!stream)) {
php_stream_wrapper_log_error(wrapper, options, "phar error: could not reopen phar \"%s\"", ZSTR_VAL(resource->host));
efree(internal_file);
php_url_free(resource);
return NULL;
}
- stream = phar_get_pharfp(phar);
}
phar_entry_info *entry;
diff --git a/ext/phar/util.c b/ext/phar/util.c
index 5e5495d8d96..fdadc4d9b6b 100644
--- a/ext/phar/util.c
+++ b/ext/phar/util.c
@@ -107,11 +107,12 @@ php_stream *phar_get_efp(phar_entry_info *entry, bool follow_links) /* {{{ */
}
if (phar_get_fp_type(entry) == PHAR_FP) {
- if (!phar_get_entrypfp(entry)) {
+ php_stream *stream = phar_get_entrypfp(entry);
+ if (!stream) {
/* re-open just in time for cases where our refcount reached 0 on the phar archive */
- phar_open_archive_fp(entry->phar);
+ stream = phar_open_archive_fp(entry->phar);
}
- return phar_get_entrypfp(entry);
+ return stream;
} else if (phar_get_fp_type(entry) == PHAR_UFP) {
return phar_get_entrypufp(entry);
} else if (entry->fp_type == PHAR_MOD) {
@@ -708,24 +709,23 @@ static inline void phar_set_pharfp(phar_archive_data *phar, php_stream *fp)
PHAR_G(cached_fp)[phar->phar_pos].fp = fp;
}
-/* initialize a phar_archive_data's read-only fp for existing phar data */
-zend_result phar_open_archive_fp(phar_archive_data *phar) /* {{{ */
+/* Initialize a phar_archive_data's read-only fp for existing phar data.
+ * The stream is owned by the `phar` object and must not be closed manually. */
+php_stream *phar_open_archive_fp(phar_archive_data *phar) /* {{{ */
{
- if (phar_get_pharfp(phar)) {
- return SUCCESS;
+ php_stream *stream = phar_get_pharfp(phar);
+ if (stream) {
+ return stream;
}
if (php_check_open_basedir(phar->fname)) {
- return FAILURE;
+ return NULL;
}
- phar_set_pharfp(phar, php_stream_open_wrapper(phar->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL));
-
- if (!phar_get_pharfp(phar)) {
- return FAILURE;
- }
+ stream = php_stream_open_wrapper(phar->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, NULL);
+ phar_set_pharfp(phar, stream);
- return SUCCESS;
+ return stream;
}
/* }}} */
@@ -829,7 +829,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_open_entry_fp(phar_entry_info *entry, ch
}
if (!phar_get_pharfp(phar)) {
- if (FAILURE == phar_open_archive_fp(phar)) {
+ if (!phar_open_archive_fp(phar)) {
spprintf(error, 4096, "phar error: Cannot open phar archive \"%s\" for reading", phar->fname);
return FAILURE;
}