@@ -3107,6 +3107,30 @@ static int phar_set_compression(zval *zv, void *argument) /* {{{ */
31073107}
31083108/* }}} */
31093109
3110+ typedef struct {
3111+ uint32_t compress ;
3112+ char * error ;
3113+ } phar_compression_args ;
3114+
3115+ static int phar_decompress_for_compression_change (zval * zv , void * argument ) /* {{{ */
3116+ {
3117+ phar_entry_info * entry = (phar_entry_info * )Z_PTR_P (zv );
3118+ phar_compression_args * args = (phar_compression_args * )argument ;
3119+ uint32_t current = entry -> flags & PHAR_ENT_COMPRESSION_MASK ;
3120+
3121+ if (entry -> is_deleted || entry -> is_dir || !current || current == args -> compress ) {
3122+ return ZEND_HASH_APPLY_KEEP ;
3123+ }
3124+
3125+ /* phar_flush() would otherwise copy the old compressed bytes as the new contents */
3126+ if (FAILURE == phar_open_entry_fp (entry , & args -> error , 0 )) {
3127+ return ZEND_HASH_APPLY_STOP ;
3128+ }
3129+
3130+ return ZEND_HASH_APPLY_KEEP ;
3131+ }
3132+ /* }}} */
3133+
31103134static int phar_test_compression (zval * zv , void * argument ) /* {{{ */
31113135{
31123136 const phar_entry_info * entry = Z_PTR_P (zv );
@@ -3133,9 +3157,18 @@ static int phar_test_compression(zval *zv, void *argument) /* {{{ */
31333157}
31343158/* }}} */
31353159
3136- static void pharobj_set_compression (HashTable * manifest , uint32_t compress ) /* {{{ */
3160+ static zend_result pharobj_set_compression (HashTable * manifest , uint32_t compress , char * * error ) /* {{{ */
31373161{
3162+ phar_compression_args args = { .compress = compress , .error = NULL };
3163+
3164+ zend_hash_apply_with_argument (manifest , phar_decompress_for_compression_change , & args );
3165+ if (args .error ) {
3166+ * error = args .error ;
3167+ return FAILURE ;
3168+ }
3169+
31383170 zend_hash_apply_with_argument (manifest , phar_set_compression , & compress );
3171+ return SUCCESS ;
31393172}
31403173/* }}} */
31413174
@@ -3326,7 +3359,11 @@ PHP_METHOD(Phar, compressFiles)
33263359 zend_throw_exception_ex (phar_ce_PharException , 0 , "phar \"%pS\" is persistent, unable to copy on write" , phar_obj -> archive -> fname );
33273360 RETURN_THROWS ();
33283361 }
3329- pharobj_set_compression (& phar_obj -> archive -> manifest , flags );
3362+ if (FAILURE == pharobj_set_compression (& phar_obj -> archive -> manifest , flags , & error )) {
3363+ zend_throw_exception_ex (spl_ce_BadMethodCallException , 0 , "%s" , error );
3364+ efree (error );
3365+ RETURN_THROWS ();
3366+ }
33303367 phar_obj -> archive -> is_modified = 1 ;
33313368 phar_flush (phar_obj -> archive , & error );
33323369
@@ -3365,7 +3402,11 @@ PHP_METHOD(Phar, decompressFiles)
33653402 zend_throw_exception_ex (phar_ce_PharException , 0 , "phar \"%pS\" is persistent, unable to copy on write" , phar_obj -> archive -> fname );
33663403 RETURN_THROWS ();
33673404 }
3368- pharobj_set_compression (& phar_obj -> archive -> manifest , PHAR_ENT_COMPRESSED_NONE );
3405+ if (FAILURE == pharobj_set_compression (& phar_obj -> archive -> manifest , PHAR_ENT_COMPRESSED_NONE , & error )) {
3406+ zend_throw_exception_ex (spl_ce_BadMethodCallException , 0 , "%s" , error );
3407+ efree (error );
3408+ RETURN_THROWS ();
3409+ }
33693410 }
33703411
33713412 phar_obj -> archive -> is_modified = 1 ;
0 commit comments