*/
PHP_METHOD(Phar, unlinkArchive)
{
- char *fname, *error;
- int fname_len;
+ char *fname, *error, *zname, *arch, *entry;
+ int fname_len, zname_len, arch_len, entry_len;
phar_archive_data *phar;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
return;
}
+ zname = zend_get_executed_filename(TSRMLS_C);
+ zname_len = strlen(zname);
+
+ if (zname_len > 7 && !memcmp(zname, "phar://", 7) && SUCCESS == phar_split_fname(zname, zname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
+ if (arch_len == fname_len && !memcmp(arch, fname, arch_len)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" cannot be unlinked from within itself", fname);
+ efree(arch);
+ efree(entry);
+ return;
+ }
+ efree(arch);
+ efree(entry);
+ }
+
if (phar->refcount) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname);
return;
var_dump(file_exists($fname));
$phar = new Phar($fname);
var_dump(count($phar));
+$phar['evil.php'] = '<?php
+try {
+Phar::unlinkArchive(Phar::running(false));
+} catch (Exception $e) {echo $e->getMessage(),"\n";}
+var_dump(Phar::running(false));
+include Phar::running(true) . "/another.php";
+?>';
+$phar['another.php'] = "hi\n";
+unset($phar);
+include $pname . '/evil.php';
?>
===DONE===
--CLEAN--
__HALT_COMPILER();"
bool(false)
int(0)
+phar archive "%sphar_unlinkarchive.phar" cannot be unlinked from within itself
+string(%d) "%sphar_unlinkarchive.phar"
+hi
===DONE===