Commit 5bed2a8920f for php.net

commit 5bed2a8920f89ce07fdecd44ed845ce544947f50
Author: Niels Dossche <7771979+ndossche@users.noreply.github.com>
Date:   Sun Nov 16 05:57:00 2025 -0800

    Avoid string copy in ZipArchive::addFromString() (#20497)

    Instead of copying the data we increment the refcount of the string.

diff --git a/UPGRADING b/UPGRADING
index 3b0301522d4..1e84b8beee9 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -130,3 +130,6 @@ PHP 8.6 UPGRADE NOTES
   . Improved performance of array_walk().
   . Improved performance of intval('+0b...', 2) and intval('0b...', 2).
   . Improved performance of str_split().
+
+- Zip:
+  . Avoid string copies in ZipArchive::addFromString().
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 40c098d8901..06bd41d602c 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -1014,7 +1014,7 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */

 	if (intern->buffers_cnt>0) {
 		for (i=0; i<intern->buffers_cnt; i++) {
-			efree(intern->buffers[i]);
+			zend_string_release(intern->buffers[i]);
 		}
 		efree(intern->buffers);
 	}
@@ -1868,17 +1868,16 @@ PHP_METHOD(ZipArchive, addFromString)

 	ze_obj = Z_ZIP_P(self);
 	if (ze_obj->buffers_cnt) {
-		ze_obj->buffers = (char **)safe_erealloc(ze_obj->buffers, sizeof(char *), (ze_obj->buffers_cnt+1), 0);
+		ze_obj->buffers = safe_erealloc(ze_obj->buffers, sizeof(*ze_obj->buffers), (ze_obj->buffers_cnt + 1), 0);
 		pos = ze_obj->buffers_cnt++;
 	} else {
-		ze_obj->buffers = (char **)emalloc(sizeof(char *));
+		ze_obj->buffers = emalloc(sizeof(*ze_obj->buffers));
 		ze_obj->buffers_cnt++;
 		pos = 0;
 	}
-	ze_obj->buffers[pos] = (char *)safe_emalloc(ZSTR_LEN(buffer), 1, 1);
-	memcpy(ze_obj->buffers[pos], ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1);
+	ze_obj->buffers[pos] = zend_string_copy(buffer);

-	zs = zip_source_buffer(intern, ze_obj->buffers[pos], ZSTR_LEN(buffer), 0);
+	zs = zip_source_buffer(intern, ZSTR_VAL(buffer), ZSTR_LEN(buffer), 0);

 	if (zs == NULL) {
 		RETURN_FALSE;
diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h
index 61e7fb8dad1..5dc7bab2500 100644
--- a/ext/zip/php_zip.h
+++ b/ext/zip/php_zip.h
@@ -68,7 +68,7 @@ typedef struct _ze_zip_read_rsrc {
 /* Extends zend object */
 typedef struct _ze_zip_object {
 	struct zip *za;
-	char **buffers;
+	zend_string **buffers;
 	HashTable *prop_handler;
 	char *filename;
 	int filename_len;