php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #58179 PHP crashes on phar recreate after unlink
Submitted: 2008-04-28 07:38 UTC Modified: 2008-05-27 14:25 UTC
From: mike at ziebeck dot net Assigned:
Status: Closed Package: phar (PECL)
PHP Version: 5_2 CVS-2008-04-28 (dev) OS: Windows XP Pro x32
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: mike at ziebeck dot net
New email:
PHP Version: OS:

 

 [2008-04-28 07:38 UTC] mike at ziebeck dot net
Description:
------------
PHP crashes if phar archive is beeing recreated and used
after it has been unlinked. Reproduce Steps:

 1] create new phar archive (DataArchive0.phar)
 2] add any file
 3] unset phar object instance
 4] unlink phar archive file (DataArchive0.phar)
 6] create new phar archive (DataArchive0.phar)
 7] add any file
 : crash 

As far as I can see:
--------------------
 * There's no difference between $p->addFromString() and
   adding via Stream wrapper using file_put_contents()
 * if stub is set before adding a file, PHP crashes here
 * if phar object instance is not unset 
   + unlinking is denied
   + archive files stay alive
   + PHP does not crash
 * creating and unlinking lots(1024) of different archives
   before using the name of the first one again does not
   matter

Using win32 snapshot version of PHP 5.2: [Problem persists]
-----------------------------------------------------------
 http://snaps.php.net/win32/php5.2-win32-200804280830.zip
 http://snaps.php.net/win32/pecl5.2-win32-200804280830.zip

Using win32 snapshot version of PHP 5.3: [Problem persists]
-----------------------------------------------------------
 http://snaps.php.net/win32/php5.3-win32-200804251230.zip
 http://snaps.php.net/win32/pecl5.3-win32-200804251230.zip
  

Reproduce code:
---------------
<?
 $dirName=str_replace(DIRECTORY_SEPARATOR, "/", dirname(__FILE__));
 $reuseDelay=1024;
 for($i=0; $i<2*$reuseDelay; $i++){
  $pArchive="DataArchive".($i%$reuseDelay).".phar";
  $p=new Phar($pPath="$dirName/$pArchive", 0, $pArchive);
  echo("\rFile($i) Name($pArchive)      ");
  //$p->setStub('<? __HALT_COMPILER(); ? >');
  $p->addFromString($i, "");
  //file_put_contents("phar://$pPath/$i", "");
  unset($p);
  unlink($pPath);
 }
 echo("\r Files written($i)                    \r\n");
?>


Expected result:
----------------
Files written(2048)

Actual result:
--------------
File(1024) Name(DataArchive0.phar)

CLI crashes, Windows asks for report

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-04-29 06:27 UTC] steph dot fox at virgin dot net
Greg, I can reproduce this crash with a single take ($reuseDelay=2) under 5_3 and XP. It comes from the first line of php_stream_seek() - it looks like the stream itself doesn't exist at this point?
 [2008-04-29 06:46 UTC] steph dot fox at virgin dot net
I just added a test for this bug in CVS.
 [2008-04-29 11:50 UTC] steph dot fox at virgin dot net
FWIW, the correct way would be to use the stream wrapper:

unlink(phar:// . $filename);

- but that actually gives a useful error about the same problem at present.

Warning: unlink(): unlink of "phar://C:\sandbox\php5\Debug_TS\DataArchive.zip" failed: phar error: file "" in phar "C:/sandbox/php5/Debug_TS/DataArchive.zip" cannot be empty in C:\sandbox\php5\Debug_TS\bug2.php on line 21

NB the file is not empty.
 [2008-04-29 12:23 UTC] steph dot fox at virgin dot net
Scratch that - it's a misleading error message. The streams approach is purely for internal files, not the entire archive after all.
 [2008-04-29 13:13 UTC] steph dot fox at virgin dot net
OK, I have a working solution:

static void phar_spl_foreign_dtor(spl_filesystem_object *object TSRMLS_DC) /* {{{ */
{
	phar_archive_data *phar_data = (phar_archive_data *) object->oth;

	--(phar_data->refcount);
	phar_archive_delref(phar_data TSRMLS_CC);
	object->oth = NULL;
}
/* }}} */

Unfortunately this will only work if SPL is enabled, so it won't always avoid that crash under PHP 5.2. Anyone have any better ideas?
 [2008-05-23 11:47 UTC] steph dot fox at virgin dot net
This bug has been fixed in CVS.

In case this was a documentation problem, the fix will show up at the
end of next Sunday (CET) on pecl.php.net.

In case this was a pecl.php.net website problem, the change will show
up on the website in short time.
 
Thank you for the report, and for helping us make PECL better.

OK, we couldn't use my idea because it would prevent caching, which would obviously slow down Web apps stored in phars to an unacceptable level.

PHP no longer crashes with this code (i.e. unset() works), but if you want to unlink a phar fully before the end of the script you'll need to use a new phar-specific unlink method, Phar::unlinkArchive(). So in order to get the behaviour you want, your code would read:
<?php

 $dirName=str_replace(DIRECTORY_SEPARATOR, "/", dirname(__FILE__));
 $reuseDelay=1024;
 for($i=0; $i<2*$reuseDelay; $i++){
  $pArchive="DataArchive".($i%$reuseDelay).".phar";
  $p=new Phar($pPath="$dirName/$pArchive", 0, $pArchive);
  echo("\rFile($i) Name($pArchive)      ");
  //$p->setStub('<? __HALT_COMPILER(); ? >');
  $p->addFromString($i, "");
  //file_put_contents("phar://$pPath/$i", "");
  unset($p);
  //unlink($pPath);
  Phar::unlinkArchive($pPath);
 }
 echo("\r Files written($i)                    \r\n");

?>
 [2008-05-27 11:40 UTC] mike at ziebeck dot net
Using win32 snapshot version of PHP 5.2: [Problem solved]
-----------------------------------------------------------
 http://snaps.php.net/win32/php5.2-win32-200805271230.zip
 http://snaps.php.net/win32/pecl5.2-win32-200805271230.zip

Using win32 snapshot version of PHP 5.3: [Problem solved]
-----------------------------------------------------------
 http://snaps.php.net/win32/php5.3-win32-200805271230.zip
 http://snaps.php.net/win32/pecl5.3-win32-200805271230.zip

-> extension disappeared: php_phar

Great Job!
 [2008-05-27 14:25 UTC] greg at chiaraquartet dot net
php_phar is gone from the pecl bunch in PHP_5_3 because it is ext/phar and built in statically to PHP, just to be clear.

Changing bug summary back, so others can find it should they run into the same problem
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Dec 27 02:01:29 2024 UTC