@@ -260,20 +260,26 @@ bool phar_archive_delref(phar_archive_data *phar) /* {{{ */
260260 PHAR_G (last_phar ) = NULL ;
261261 PHAR_G (last_phar_name ) = PHAR_G (last_alias ) = NULL ;
262262
263+ /* This is a new phar that has perhaps had an alias/metadata set, but has never been flushed. */
264+ bool remove_fname_cache = !zend_hash_num_elements (& phar -> manifest );
265+
263266 if (phar -> fp && (!(phar -> flags & PHAR_FILE_COMPRESSION_MASK ) || !phar -> alias )) {
264267 /* close open file handle - allows removal or rename of
265268 the file on windows, which has greedy locking
266- only close if the archive was not already compressed. If it
267- was compressed, then the fp does not refer to the original file.
268- We're also closing compressed files to save resources,
269- but only if the archive isn't aliased. */
269+ only close if the archive was not already compressed.
270+ We're also closing compressed files to save resources, but only if the archive isn't aliased.
271+ If it was compressed, then the fp does not refer to the original compressed file:
272+ it refers to the **uncompressed** filtered file stream.
273+ Therefore, upon closing a compressed file we need to invalidate the phar archive such
274+ that the code that reopens the phar will not try to use the **compressed** file as if it was uncompressed.
275+ That would result in treating compressed file data as if it were compressed and using uncompressed file offsets
276+ on the compressed file. */
270277 php_stream_close (phar -> fp );
271278 phar -> fp = NULL ;
279+ remove_fname_cache |= phar -> flags & PHAR_FILE_COMPRESSION_MASK ;
272280 }
273281
274- if (!zend_hash_num_elements (& phar -> manifest )) {
275- /* this is a new phar that has perhaps had an alias/metadata set, but has never
276- been flushed */
282+ if (remove_fname_cache ) {
277283 if (zend_hash_str_del (& (PHAR_G (phar_fname_map )), phar -> fname , phar -> fname_len ) != SUCCESS ) {
278284 phar_destroy_phar_data (phar );
279285 }
0 commit comments