@@ -3173,6 +3173,30 @@ static int phar_set_compression(zval *zv, void *argument) /* {{{ */
31733173}
31743174/* }}} */
31753175
3176+ typedef struct {
3177+ uint32_t compress ;
3178+ char * error ;
3179+ } phar_compression_args ;
3180+
3181+ static int phar_decompress_for_compression_change (zval * zv , void * argument ) /* {{{ */
3182+ {
3183+ phar_entry_info * entry = (phar_entry_info * )Z_PTR_P (zv );
3184+ phar_compression_args * args = (phar_compression_args * )argument ;
3185+ uint32_t current = entry -> flags & PHAR_ENT_COMPRESSION_MASK ;
3186+
3187+ if (entry -> is_deleted || entry -> is_dir || !current || current == args -> compress ) {
3188+ return ZEND_HASH_APPLY_KEEP ;
3189+ }
3190+
3191+ /* phar_flush() would otherwise copy the old compressed bytes as the new contents */
3192+ if (FAILURE == phar_open_entry_fp (entry , & args -> error , 0 )) {
3193+ return ZEND_HASH_APPLY_STOP ;
3194+ }
3195+
3196+ return ZEND_HASH_APPLY_KEEP ;
3197+ }
3198+ /* }}} */
3199+
31763200static int phar_test_compression (zval * zv , void * argument ) /* {{{ */
31773201{
31783202 phar_entry_info * entry = (phar_entry_info * )Z_PTR_P (zv );
@@ -3197,9 +3221,18 @@ static int phar_test_compression(zval *zv, void *argument) /* {{{ */
31973221}
31983222/* }}} */
31993223
3200- static void pharobj_set_compression (HashTable * manifest , uint32_t compress ) /* {{{ */
3224+ static zend_result pharobj_set_compression (HashTable * manifest , uint32_t compress , char * * error ) /* {{{ */
32013225{
3226+ phar_compression_args args = { .compress = compress , .error = NULL };
3227+
3228+ zend_hash_apply_with_argument (manifest , phar_decompress_for_compression_change , & args );
3229+ if (args .error ) {
3230+ * error = args .error ;
3231+ return FAILURE ;
3232+ }
3233+
32023234 zend_hash_apply_with_argument (manifest , phar_set_compression , & compress );
3235+ return SUCCESS ;
32033236}
32043237/* }}} */
32053238
@@ -3390,7 +3423,11 @@ PHP_METHOD(Phar, compressFiles)
33903423 zend_throw_exception_ex (phar_ce_PharException , 0 , "phar \"%s\" is persistent, unable to copy on write" , phar_obj -> archive -> fname );
33913424 RETURN_THROWS ();
33923425 }
3393- pharobj_set_compression (& phar_obj -> archive -> manifest , flags );
3426+ if (FAILURE == pharobj_set_compression (& phar_obj -> archive -> manifest , flags , & error )) {
3427+ zend_throw_exception_ex (spl_ce_BadMethodCallException , 0 , "%s" , error );
3428+ efree (error );
3429+ RETURN_THROWS ();
3430+ }
33943431 phar_obj -> archive -> is_modified = 1 ;
33953432 phar_flush (phar_obj -> archive , & error );
33963433
@@ -3432,7 +3469,11 @@ PHP_METHOD(Phar, decompressFiles)
34323469 zend_throw_exception_ex (phar_ce_PharException , 0 , "phar \"%s\" is persistent, unable to copy on write" , phar_obj -> archive -> fname );
34333470 RETURN_THROWS ();
34343471 }
3435- pharobj_set_compression (& phar_obj -> archive -> manifest , PHAR_ENT_COMPRESSED_NONE );
3472+ if (FAILURE == pharobj_set_compression (& phar_obj -> archive -> manifest , PHAR_ENT_COMPRESSED_NONE , & error )) {
3473+ zend_throw_exception_ex (spl_ce_BadMethodCallException , 0 , "%s" , error );
3474+ efree (error );
3475+ RETURN_THROWS ();
3476+ }
34363477 }
34373478
34383479 phar_obj -> archive -> is_modified = 1 ;
0 commit comments