Commit 4985676d96e for php
commit 4985676d96ef33acd413b9fe595747676b73cd33
Merge: be420663e32 66bbbe5fd04
Author: Weilin Du <weilindu@php.net>
Date: Fri Oct 9 00:55:01 2026 +0800
Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5:
ext/zip: Reject ZipArchive mutators during close() (#24025)
diff --cc NEWS
index cce4f4a0ee4,7b8426b2b51..c895aa7b1dd
--- a/NEWS
+++ b/NEWS
@@@ -25,8 -17,11 +25,11 @@@ PH
- Zip:
. Fixed use-after-free when re-entering ZipArchive during destruction or
a close warning, and rejected opening streams while closing. (jvoisin)
+ . Fixed a use-after-free when a ZipArchive method that modifies the archive
+ is called from a progress or cancel callback during close().
+ (Ilia Alshanetsky)
-22 Oct 2026, PHP 8.5.12
+08 Oct 2026, PHP 8.6.0RC3
- BCMath:
. Fixed BcMath\Number results that truncate to zero keeping a negative sign
diff --cc ext/zip/php_zip.c
index fc2998a7ca3,7f95f55a3ca..5baecfc1893
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@@ -1945,8 -1864,12 +1953,12 @@@ static void php_zip_add_from_pattern(IN
RETURN_THROWS();
}
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
if (type == 1) {
- found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), glob_flags, return_value);
+ found = php_zip_glob(pattern, glob_flags, return_value);
} else {
found = php_zip_pcre(pattern, path, path_len, return_value);
}
@@@ -2079,8 -2002,16 +2091,12 @@@ PHP_METHOD(ZipArchive, addFile
entry_name_len = ZSTR_LEN(filename);
}
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
- entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
+ entry_name, entry_name_len, offset_start, offset_len, -1, flags) == SUCCESS);
}
/* }}} */
@@@ -2108,8 -2039,16 +2124,12 @@@ PHP_METHOD(ZipArchive, replaceFile
RETURN_THROWS();
}
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
- NULL, 0, offset_start, offset_len, index, flags) < 0) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
+ NULL, 0, offset_start, offset_len, index, flags) == SUCCESS);
}
/* }}} */
@@@ -2132,8 -2073,24 +2152,12 @@@ PHP_METHOD(ZipArchive, addFromString
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
ze_obj = Z_ZIP_P(self);
- archive = ze_obj->archive;
- if (archive->buffers_cnt) {
- archive->buffers = (char **)safe_erealloc(archive->buffers, sizeof(char *), (archive->buffers_cnt+1), 0);
- pos = archive->buffers_cnt++;
- } else {
- archive->buffers = (char **)emalloc(sizeof(char *));
- archive->buffers_cnt++;
- pos = 0;
- }
- archive->buffers[pos] = (char *)safe_emalloc(ZSTR_LEN(buffer), 1, 1);
- memcpy(archive->buffers[pos], ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1);
-
- zs = zip_source_buffer(intern, archive->buffers[pos], ZSTR_LEN(buffer), 0);
+ zs = php_zip_create_string_source(buffer, NULL, NULL);
if (zs == NULL) {
RETURN_FALSE;
@@@ -2306,7 -2271,15 +2334,11 @@@ PHP_METHOD(ZipArchive, setArchiveFlag
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (zip_set_archive_flag(intern, flag, (int)value)) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(zip_set_archive_flag(intern, flag, (int)value) == 0);
}
PHP_METHOD(ZipArchive, getArchiveFlag)
@@@ -2438,9 -2426,16 +2482,13 @@@ PHP_METHOD(ZipArchive, setExternalAttri
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
- if (zip_file_set_external_attributes(intern, (zip_uint64_t)index,
- (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
+ RETURN_BOOL(zip_file_set_external_attributes(intern, (zip_uint64_t)index,
+ (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) == 0);
}
/* }}} */
@@@ -2558,7 -2568,19 +2610,11 @@@ PHP_METHOD(ZipArchive, setEncryptionInd
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (UNEXPECTED(zip_file_set_encryption(intern, index, ZIP_EM_NONE, NULL) < 0)) {
- php_error_docref(NULL, E_WARNING, "password reset failed");
- RETURN_FALSE;
- }
-
- if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
+ RETURN_BOOL(php_zip_file_set_encryption(intern, index, method, password));
}
/* }}} */
#endif
@@@ -2646,13 -2664,11 +2702,18 @@@ PHP_METHOD(ZipArchive, setCompressionNa
RETURN_THROWS();
}
- if (name_len == 0) {
- zend_argument_must_not_be_empty_error(1);
+ if (comp_flags < 0 || comp_flags > USHRT_MAX) {
+ // comp_flags is cast down accordingly in libzip, zip_entry_t compression_level is of zip_uint16_t
+ zend_argument_value_error(3, "must be between 0 and %u", USHRT_MAX);
+ RETURN_THROWS();
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
++
++ if (php_zipobj_closing(Z_ZIP_P(this))) {
+ RETURN_THROWS();
+ }
+
idx = zip_name_locate(intern, name, 0);
if (idx < 0) {
@@@ -2677,25 -2696,17 +2738,29 @@@ PHP_METHOD(ZipArchive, setCompressionIn
RETURN_THROWS();
}
+ if (index < 0) {
+ RETURN_FALSE;
+ }
+
+ if (comp_method < -1 || comp_method > INT_MAX) {
+ zend_argument_value_error(2, "must be between -1 and %d", INT_MAX);
+ RETURN_THROWS();
+ }
+
+ if (comp_flags < 0 || comp_flags > USHRT_MAX) {
+ // comp_flags is cast down accordingly in libzip, zip_entry_t compression_level is of zip_uint16_t
+ zend_argument_value_error(3, "must be between 0 and %u", USHRT_MAX);
+ RETURN_THROWS();
+ }
+
ZIP_FROM_OBJECT(intern, this);
+ if (php_zipobj_closing(Z_ZIP_P(this))) {
+ RETURN_THROWS();
+ }
+
- if (zip_set_file_compression(intern, (zip_uint64_t)index,
- (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
+ RETURN_BOOL(zip_set_file_compression(intern, (zip_uint64_t)index,
+ (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) == 0);
}
/* }}} */
@@@ -2719,8 -2732,11 +2784,12 @@@ PHP_METHOD(ZipArchive, setMtimeName
RETURN_THROWS();
}
- if (name_len == 0) {
- zend_argument_must_not_be_empty_error(1);
+ ZIP_FROM_OBJECT(intern, this);
+
++ if (php_zipobj_closing(Z_ZIP_P(this))) {
+ RETURN_THROWS();
+ }
+
idx = zip_name_locate(intern, name, 0);
if (idx < 0) {
@@@ -2747,10 -2766,18 +2816,14 @@@ PHP_METHOD(ZipArchive, setMtimeIndex
ZIP_FROM_OBJECT(intern, this);
+ if (php_zipobj_closing(Z_ZIP_P(this))) {
+ RETURN_THROWS();
+ }
+
- if (zip_file_set_mtime(intern, (zip_uint64_t)index,
- (time_t)mtime, (zip_uint32_t)flags) != 0) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
+ RETURN_BOOL(zip_file_set_mtime(intern, (zip_uint64_t)index,
+ (time_t)mtime, (zip_uint32_t)flags) == 0);
}
/* }}} */
-#endif
/* {{{ Delete a file using its index */
PHP_METHOD(ZipArchive, deleteIndex)
@@@ -2786,15 -2821,21 +2863,19 @@@ PHP_METHOD(ZipArchive, deleteName
RETURN_THROWS();
}
+ if (name_len < 1) {
+ RETURN_FALSE;
+ }
+
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (name_len < 1) {
- RETURN_FALSE;
- }
-
PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
- if (zip_delete(intern, sb.index)) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
+
+ RETURN_BOOL(zip_delete(intern, sb.index) == 0);
}
/* }}} */
@@@ -2820,9 -2867,11 +2901,13 @@@ PHP_METHOD(ZipArchive, renameIndex
RETURN_THROWS();
}
- if (zip_file_rename(intern, index, (const char *)new_name, 0) != 0) {
- RETURN_FALSE;
+ ZIP_FROM_OBJECT(intern, self);
+
++ if (php_zipobj_closing(Z_ZIP_P(self))) {
++ RETURN_THROWS();
+ }
+
- RETURN_TRUE;
+ RETURN_BOOL(zip_file_rename(intern, index, (const char *)new_name, 0) == 0);
}
/* }}} */
@@@ -2863,13 -2920,21 +2952,17 @@@ PHP_METHOD(ZipArchive, unchangeIndex
RETURN_THROWS();
}
+ if (index < 0) {
+ RETURN_FALSE;
+ }
+
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (index < 0) {
- RETURN_FALSE;
- }
-
- if (zip_unchange(intern, index) != 0) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(zip_unchange(intern, index) == 0);
}
/* }}} */
@@@ -2886,15 -2951,23 +2979,19 @@@ PHP_METHOD(ZipArchive, unchangeName
RETURN_THROWS();
}
+ if (name_len < 1) {
+ RETURN_FALSE;
+ }
+
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (name_len < 1) {
- RETURN_FALSE;
- }
-
PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
- if (zip_unchange(intern, sb.index) != 0) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(zip_unchange(intern, sb.index) == 0);
}
/* }}} */
@@@ -2908,7 -2983,15 +3005,11 @@@ PHP_METHOD(ZipArchive, unchangeAll
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (zip_unchange_all(intern) != 0) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(zip_unchange_all(intern) == 0);
}
/* }}} */
@@@ -2922,7 -3007,15 +3023,11 @@@ PHP_METHOD(ZipArchive, unchangeArchive
ZIP_FROM_OBJECT(intern, self);
+ if (php_zipobj_closing(Z_ZIP_P(self))) {
+ RETURN_THROWS();
+ }
+
- if (zip_unchange_archive(intern) != 0) {
- RETURN_FALSE;
- } else {
- RETURN_TRUE;
- }
+ RETURN_BOOL(zip_unchange_archive(intern) == 0);
}
/* }}} */