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;
  }