Commit 66bbbe5fd04 for php
commit 66bbbe5fd049790dee5cc98c30028b3c3e5408f2
Merge: 89b1f7199e8 acd5fe8b6ad
Author: Weilin Du <weilindu@php.net>
Date: Fri Oct 9 00:54:41 2026 +0800
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
ext/zip: Reject ZipArchive mutators during close() (#24025)
diff --cc NEWS
index 734c2577921,94ac095afc9..7b8426b2b51
--- a/NEWS
+++ b/NEWS
@@@ -17,8 -23,19 +17,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.4.27
+22 Oct 2026, PHP 8.5.12
- BCMath:
. Fixed BcMath\Number results that truncate to zero keeping a negative sign
diff --cc ext/zip/php_zip.c
index 8fce5d4a2c2,81ed391ee3a..7f95f55a3ca
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@@ -632,8 -638,50 +632,17 @@@ static char * php_zipobj_get_zip_commen
}
/* }}} */
+ static bool php_zipobj_closing(ze_zip_object *obj)
+ {
+ if (obj->archive && obj->archive->close) {
+ zend_throw_error(NULL, "Already being closed");
+ return true;
+ }
+ return false;
+ }
+
-#ifdef HAVE_GLOB /* {{{ */
-#ifndef GLOB_ONLYDIR
-#define GLOB_ONLYDIR (1<<30)
-#define GLOB_EMULATE_ONLYDIR
-#define GLOB_FLAGMASK (~GLOB_ONLYDIR)
-#else
-#define GLOB_FLAGMASK (~0)
-#endif
-#ifndef GLOB_BRACE
-# define GLOB_BRACE 0
-#endif
-#ifndef GLOB_MARK
-# define GLOB_MARK 0
-#endif
-#ifndef GLOB_NOSORT
-# define GLOB_NOSORT 0
-#endif
-#ifndef GLOB_NOCHECK
-# define GLOB_NOCHECK 0
-#endif
-#ifndef GLOB_NOESCAPE
-# define GLOB_NOESCAPE 0
-#endif
-#ifndef GLOB_ERR
-# define GLOB_ERR 0
-#endif
-
-/* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
-#define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
-
-#endif /* }}} */
-
int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_value) /* {{{ */
{
-#ifdef HAVE_GLOB
int cwd_skip = 0;
#ifdef ZTS
char cwd[MAXPATHLEN];
@@@ -3180,31 -3339,29 +3291,35 @@@ static void php_zip_progress_callback(z
PHP_METHOD(ZipArchive, registerProgressCallback)
{
struct zip *intern;
- zval *self = ZEND_THIS;
double rate;
- zend_fcall_info fci;
+ zend_fcall_info dummy_fci;
zend_fcall_info_cache fcc;
php_zip_archive *archive;
+ ze_zip_object *obj;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "df", &rate, &fci, &fcc) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "dF", &rate, &dummy_fci, &fcc) == FAILURE) {
RETURN_THROWS();
}
-
- ZIP_FROM_OBJECT(intern, self);
-
- if (php_zipobj_closing(Z_ZIP_P(self))) {
+ /* Inline ZIP_FROM_OBJECT(intern, self); */
+ obj = Z_ZIP_P(ZEND_THIS);
+ intern = php_zip_object_za(obj);
+ if (!intern) {
+ zend_value_error("Invalid or uninitialized Zip object");
+ zend_release_fcall_info_cache(&fcc);
RETURN_THROWS();
}
-
- archive = Z_ZIP_P(self)->archive;
++ if (php_zipobj_closing(obj)) {
++ zend_release_fcall_info_cache(&fcc);
++ RETURN_THROWS();
++ }
+ archive = obj->archive;
/* register */
- if (zip_register_progress_callback_with_state(intern, rate, _php_zip_progress_callback, _php_zip_progress_callback_free, archive)) {
+ if (zip_register_progress_callback_with_state(intern, rate, php_zip_progress_callback, php_zip_progress_callback_free, archive)) {
+ zend_release_fcall_info_cache(&fcc);
RETURN_FALSE;
}
- ZVAL_COPY(&archive->progress_callback, &fci.function_name);
+ zend_fcc_dup(&archive->progress_callback, &fcc);
RETURN_TRUE;
}
@@@ -3247,22 -3395,19 +3362,26 @@@ PHP_METHOD(ZipArchive, registerCancelCa
RETURN_THROWS();
}
- ZIP_FROM_OBJECT(intern, self);
-
- if (php_zipobj_closing(Z_ZIP_P(self))) {
+ /* Inline ZIP_FROM_OBJECT(intern, self); */
+ obj = Z_ZIP_P(ZEND_THIS);
+ intern = php_zip_object_za(obj);
+ if (!intern) {
+ zend_value_error("Invalid or uninitialized Zip object");
+ zend_release_fcall_info_cache(&fcc);
RETURN_THROWS();
}
-
- archive = Z_ZIP_P(self)->archive;
++ if (php_zipobj_closing(obj)) {
++ zend_release_fcall_info_cache(&fcc);
++ RETURN_THROWS();
++ }
+ archive = obj->archive;
/* register */
- if (zip_register_cancel_callback_with_state(intern, _php_zip_cancel_callback, _php_zip_cancel_callback_free, archive)) {
+ if (zip_register_cancel_callback_with_state(intern, php_zip_cancel_callback, php_zip_cancel_callback_free, archive)) {
+ zend_release_fcall_info_cache(&fcc);
RETURN_FALSE;
}
- ZVAL_COPY(&archive->cancel_callback, &fci.function_name);
+ zend_fcc_dup(&archive->cancel_callback, &fcc);
RETURN_TRUE;
}