Commit 524e66be8d4 for php

commit 524e66be8d455744d8571456a972ee501b54fce8
Merge: 63045d5b991 c673cabdc36
Author: Weilin Du <weilindu@php.net>
Date:   Sat Oct 31 01:56:53 2026 +0800

    Merge branch 'PHP-8.5' into PHP-8.6

    * PHP-8.5:
      Fix GH-8469: Phar::decompressFiles() keeps compressed contents (#25045)

diff --cc NEWS
index e3bd3398dc6,cb05e526f7f..bc9ffaebcff
--- a/NEWS
+++ b/NEWS
@@@ -123,11 -196,9 +123,13 @@@ PH
    . Fixed bug GH-25006 (getColumnMeta() reads out of bounds for an
      out-of-range column index). (Ilia Alshanetsky)

 +- PDO_PGSQL:
 +  . Fixed bug GH-24461 (DISCARD ALL on persistent connection cleanup drops
 +    PgBouncer's prepared statements). (David Carlier, Artem Ukrainskiy)
 +
  - Phar:
+   . Fixed bug GH-8469 (Phar::decompressFiles() and Phar::compressFiles() retain
+     compressed contents after changing compression). (Raphael Paez)
    . Fixed bug GH-24740 (Oversized tar metadata exhausts the memory limit).
      (Lazizbek Ergashev)

diff --cc ext/phar/phar_object.c
index c45ae86a3fa,9551003edad..d43dd4ca4f0
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@@ -3107,9 -3173,33 +3107,33 @@@ static int phar_set_compression(zval *z
  }
  /* }}} */

+ typedef struct {
+ 	uint32_t compress;
+ 	char *error;
+ } phar_compression_args;
+
+ static int phar_decompress_for_compression_change(zval *zv, void *argument) /* {{{ */
+ {
+ 	phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
+ 	phar_compression_args *args = (phar_compression_args *)argument;
+ 	uint32_t current = entry->flags & PHAR_ENT_COMPRESSION_MASK;
+
+ 	if (entry->is_deleted || entry->is_dir || !current || current == args->compress) {
+ 		return ZEND_HASH_APPLY_KEEP;
+ 	}
+
+ 	/* phar_flush() would otherwise copy the old compressed bytes as the new contents */
+ 	if (FAILURE == phar_open_entry_fp(entry, &args->error, 0)) {
+ 		return ZEND_HASH_APPLY_STOP;
+ 	}
+
+ 	return ZEND_HASH_APPLY_KEEP;
+ }
+ /* }}} */
+
  static int phar_test_compression(zval *zv, void *argument) /* {{{ */
  {
 -	phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
 +	const phar_entry_info *entry = Z_PTR_P(zv);

  	if (entry->is_deleted) {
  		return ZEND_HASH_APPLY_KEEP;
@@@ -3323,10 -3420,14 +3356,14 @@@ PHP_METHOD(Phar, compressFiles
  	}

  	if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
 -		zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
 +		zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%pS\" is persistent, unable to copy on write", phar_obj->archive->fname);
  		RETURN_THROWS();
  	}
- 	pharobj_set_compression(&phar_obj->archive->manifest, flags);
+ 	if (FAILURE == pharobj_set_compression(&phar_obj->archive->manifest, flags, &error)) {
+ 		zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
+ 		efree(error);
+ 		RETURN_THROWS();
+ 	}
  	phar_obj->archive->is_modified = 1;
  	phar_flush(phar_obj->archive, &error);

@@@ -3362,10 -3466,14 +3399,14 @@@ PHP_METHOD(Phar, decompressFiles
  		RETURN_TRUE;
  	} else {
  		if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
 -			zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
 +			zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%pS\" is persistent, unable to copy on write", phar_obj->archive->fname);
  			RETURN_THROWS();
  		}
- 		pharobj_set_compression(&phar_obj->archive->manifest, PHAR_ENT_COMPRESSED_NONE);
+ 		if (FAILURE == pharobj_set_compression(&phar_obj->archive->manifest, PHAR_ENT_COMPRESSED_NONE, &error)) {
+ 			zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
+ 			efree(error);
+ 			RETURN_THROWS();
+ 		}
  	}

  	phar_obj->archive->is_modified = 1;