Bug #75101 [NEW]: `PharData` caches file contents, even through file deletion

From: Date: Mon, 21 Aug 2017 09:29:14 +0000
Subject: Bug #75101 [NEW]: `PharData` caches file contents, even through file deletion
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-210765@lists.php.net to get a copy of this message
From:             d28b312d at opayq dot com
Operating system: Windows 10 + Cygwin
PHP version:      Irrelevant
Package:          PHAR related
Bug Type:         Bug
Bug description:PharData caches file contents, even through file deletion

Description:
------------
 - PHP shipped with Cygwin (7.0.19), can't find anything in the patch
notes to suggest this is fixed in newer versions.

PharData seems to cache file contents even when the file is no longer
on the disk. Constructing a new PharData with the same filename will
produce the same object as before. I understand there is an alias
parameter, but this seems like totally unexpected behaviour especially
as these functions seem to be the go-to functions for extracting tar
archives these days.

Looking in the source code I see that this seems to be partially
deliberate behaviour as phar_open_parsed_phar tries to open an already
existing phar file, however, if the file has been deleted off disk and a
new PharData object is created then surely new data should be loaded?
Also does this mean that once a PharData object is created and a tar
file opened that the entire contents of the tar is held in memory for
the duration of the PHP script?

There seems to be no way to remove this caching, as shown in the test
script the tgz file is removed and then opened again with a new file
(with different contents), and yet the same file is opened somehow.

I've tried calling unset() on the PharData object before creating a
new one or calling clearstatcache(), but to no avail.

Interestingly and of note, even though the default format is
Phar::TAR, it seems that it auto-detects TGZ files and decompresses
them fine.

Test script:
---------------
<?php

$url = 'http://thrysoee.dk/editline/libedit-%s-3.1.tar.gz';
$downloadFile = '/tmp/foo.tgz';

file_put_contents($downloadFile, fopen(sprintf($url, '20170329'),
'r'));
var_dump(new PharData($downloadFile));

unlink($downloadFile);

file_put_contents($downloadFile, fopen(sprintf($url, '20160903'),
'r'));
var_dump(new PharData($downloadFile));

Expected result:
----------------
I expect the second object to be the new file, as shown in the edited
output below:

/tmp $ php /tmp/phpbugtest.php
object(PharData)#1 (4) {
  ["pathName":"SplFileInfo":private]=>
  string(40) "phar:///tmp/foo.tgz/libedit-20170329-3.1"
  ["fileName":"SplFileInfo":private]=>
  string(20) "libedit-20170329-3.1"
  ["glob":"DirectoryIterator":private]=>
  bool(false)
  ["subPathName":"RecursiveDirectoryIterator":private]=>
  string(0) ""
}
object(PharData)#2 (4) {
  ["pathName":"SplFileInfo":private]=>
  string(40) "phar:///tmp/foo.tgz/libedit-20160603-3.1"
  ["fileName":"SplFileInfo":private]=>
  string(20) "libedit-20160603-3.1"
  ["glob":"DirectoryIterator":private]=>
  bool(false)
  ["subPathName":"RecursiveDirectoryIterator":private]=>
  string(0) ""
}

Actual result:
--------------
/tmp $ php /tmp/phpbugtest.php
object(PharData)#1 (4) {
  ["pathName":"SplFileInfo":private]=>
  string(40) "phar:///tmp/foo.tgz/libedit-20170329-3.1"
  ["fileName":"SplFileInfo":private]=>
  string(20) "libedit-20170329-3.1"
  ["glob":"DirectoryIterator":private]=>
  bool(false)
  ["subPathName":"RecursiveDirectoryIterator":private]=>
  string(0) ""
}
object(PharData)#1 (4) {
  ["pathName":"SplFileInfo":private]=>
  string(40) "phar:///tmp/foo.tgz/libedit-20170329-3.1"
  ["fileName":"SplFileInfo":private]=>
  string(20) "libedit-20170329-3.1"
  ["glob":"DirectoryIterator":private]=>
  bool(false)
  ["subPathName":"RecursiveDirectoryIterator":private]=>
  string(0) ""
}

-- 
Edit bug report at https://bugs.php.net/bug.php?id=75101&edit=1
-- 
Try a snapshot (PHP 5.4):   https://bugs.php.net/fix.php?id=75101&r=trysnapshot54
Try a snapshot (PHP 5.5):   https://bugs.php.net/fix.php?id=75101&r=trysnapshot55
Try a snapshot (trunk):     https://bugs.php.net/fix.php?id=75101&r=trysnapshottrunk
Fixed in SVN:               https://bugs.php.net/fix.php?id=75101&r=fixed
Fixed in release:           https://bugs.php.net/fix.php?id=75101&r=alreadyfixed
Need backtrace:             https://bugs.php.net/fix.php?id=75101&r=needtrace
Need Reproduce Script:      https://bugs.php.net/fix.php?id=75101&r=needscript
Try newer version:          https://bugs.php.net/fix.php?id=75101&r=oldversion
Not developer issue:        https://bugs.php.net/fix.php?id=75101&r=support
Expected behavior:          https://bugs.php.net/fix.php?id=75101&r=notwrong
Not enough info:            https://bugs.php.net/fix.php?id=75101&r=notenoughinfo
Submitted twice:            https://bugs.php.net/fix.php?id=75101&r=submittedtwice
register_globals:           https://bugs.php.net/fix.php?id=75101&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=75101&r=php4
Daylight Savings:           https://bugs.php.net/fix.php?id=75101&r=dst
IIS Stability:              https://bugs.php.net/fix.php?id=75101&r=isapi
Install GNU Sed:            https://bugs.php.net/fix.php?id=75101&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=75101&r=float
No Zend Extensions:         https://bugs.php.net/fix.php?id=75101&r=nozend
MySQL Configuration Error:  https://bugs.php.net/fix.php?id=75101&r=mysqlcfg



Thread (4 messages)

« previous php.bugs (#210765) next »