Commit 2582710169b for php.net

commit 2582710169ba18e5bd7515f1f36baae894e13f19
Author: Gina Peter Banyard <girgias@php.net>
Date:   Fri May 8 08:46:37 2026 +0100

    ext/phar: refactor phar_copy_cached_phar() to return allocated pointer (#21978)

    Rather than changing the pointer to another phar, something extremely confusing

diff --git a/ext/phar/util.c b/ext/phar/util.c
index c1e752a8e6b..2ab20bbd28e 100644
--- a/ext/phar/util.c
+++ b/ext/phar/util.c
@@ -2008,14 +2008,13 @@ static void phar_manifest_copy_ctor(zval *zv) /* {{{ */
 }
 /* }}} */

-static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */
+static phar_archive_data* phar_copy_cached_phar(const phar_archive_data *persistent_phar) /* {{{ */
 {
-	phar_archive_data *phar;
 	HashTable newmanifest;
 	phar_archive_object *objphar;

-	phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
-	*phar = **pphar;
+	phar_archive_data *phar = emalloc(sizeof(phar_archive_data));
+	*phar = *persistent_phar;
 	phar->is_persistent = 0;
 	zend_string_addref(phar->fname);

@@ -2029,17 +2028,13 @@ static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */

 	phar_metadata_tracker_clone(&phar->metadata_tracker);

-	zend_hash_init(&newmanifest, sizeof(phar_entry_info),
-		zend_get_hash_value, destroy_phar_manifest_entry, 0);
-	zend_hash_copy(&newmanifest, &(*pphar)->manifest, phar_manifest_copy_ctor);
+	zend_hash_init(&newmanifest, sizeof(phar_entry_info), NULL, destroy_phar_manifest_entry, 0);
+	zend_hash_copy(&newmanifest, &persistent_phar->manifest, phar_manifest_copy_ctor);
 	zend_hash_apply_with_argument(&newmanifest, phar_update_cached_entry, (void *)phar);
 	phar->manifest = newmanifest;
-	zend_hash_init(&phar->mounted_dirs, sizeof(char *),
-		zend_get_hash_value, NULL, 0);
-	zend_hash_init(&phar->virtual_dirs, sizeof(char *),
-		zend_get_hash_value, NULL, 0);
-	zend_hash_copy(&phar->virtual_dirs, &(*pphar)->virtual_dirs, NULL);
-	*pphar = phar;
+	zend_hash_init(&phar->mounted_dirs, sizeof(char *), NULL, NULL, 0);
+	zend_hash_init(&phar->virtual_dirs, sizeof(char *), NULL, NULL, 0);
+	zend_hash_copy(&phar->virtual_dirs, &persistent_phar->virtual_dirs, NULL);

 	/* now, scan the list of persistent Phar objects referencing this phar and update the pointers */
 	ZEND_HASH_MAP_FOREACH_PTR(&PHAR_G(phar_persist_map), objphar) {
@@ -2047,29 +2042,26 @@ static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */
 			objphar->archive = phar;
 		}
 	} ZEND_HASH_FOREACH_END();
+	return phar;
 }
 /* }}} */

 zend_result phar_copy_on_write(phar_archive_data **pphar) /* {{{ */
 {
-	zval zv, *pzv;
-	phar_archive_data *newpphar;
+	phar_archive_data *newpphar = phar_copy_cached_phar(*pphar);

-	ZVAL_PTR(&zv, *pphar);
-	pzv = zend_hash_add(&(PHAR_G(phar_fname_map)), (*pphar)->fname, &zv);
+	zval *pzv = zend_hash_add_ptr(&(PHAR_G(phar_fname_map)), newpphar->fname, newpphar);
 	if (!pzv) {
 		return FAILURE;
 	}

-	phar_copy_cached_phar((phar_archive_data **)&Z_PTR_P(pzv));
-	newpphar = Z_PTR_P(pzv);
 	/* invalidate phar cache */
 	PHAR_G(last_phar) = NULL;
 	PHAR_G(last_alias) = NULL;
 	PHAR_G(last_phar_name) = NULL;

 	if (newpphar->alias_len && NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), newpphar->alias, newpphar->alias_len, newpphar)) {
-		zend_hash_del(&(PHAR_G(phar_fname_map)), (*pphar)->fname);
+		zend_hash_del(&(PHAR_G(phar_fname_map)), newpphar->fname);
 		return FAILURE;
 	}