Navigation Menu

Skip to content

Commit

Permalink
fix weird alias issues, add tests to check for new-found problems
Browse files Browse the repository at this point in the history
  • Loading branch information
Greg Beaver committed May 12, 2008
1 parent ac8ea81 commit 82dc039
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 61 deletions.
55 changes: 35 additions & 20 deletions ext/phar/phar.c
Expand Up @@ -420,10 +420,8 @@ int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_len, int
if (pphar) {
*pphar = NULL;
}
if (phar && alias && (options & REPORT_ERRORS)) {
if (error) {
spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, phar->fname, fname);
}
if (phar && error && !(options & REPORT_ERRORS)) {
efree(error);
}
return FAILURE;
}
Expand Down Expand Up @@ -984,6 +982,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int
int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
{
const char *ext_str, *z;
char *my_error;
int ext_len;
phar_archive_data **test, *unused = NULL;

Expand All @@ -1005,7 +1004,7 @@ int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int al
}

check_file:
if (phar_open_loaded(fname, fname_len, alias, alias_len, is_data, options, test, 0 TSRMLS_CC) == SUCCESS) {
if (phar_open_loaded(fname, fname_len, alias, alias_len, is_data, options, test, &my_error TSRMLS_CC) == SUCCESS) {
if (pphar) {
*pphar = *test;
}
Expand All @@ -1026,6 +1025,13 @@ int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int al
(*test)->is_writeable = 1;
}
return SUCCESS;
} else if (my_error) {
if (error) {
*error = my_error;
} else {
efree(my_error);
}
return FAILURE;
}

if (ext_len > 3 && (z = memchr(ext_str, 'z', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ip", 2)) {
Expand All @@ -1045,7 +1051,6 @@ int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int al
int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
{
phar_archive_data *mydata;
int register_alias;
php_stream *fp;
char *actual = NULL, *p;

Expand Down Expand Up @@ -1126,36 +1131,46 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
zend_get_hash_value, NULL, 0);
mydata->fname_len = fname_len;
if (is_data) {
alias = NULL;
alias_len = 0;
} else {
mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
mydata->alias_len = alias ? alias_len : fname_len;
}
snprintf(mydata->version, sizeof(mydata->version), "%s", PHP_PHAR_API_VERSION);
mydata->is_temporary_alias = alias ? 0 : 1;
mydata->internal_file_start = -1;
mydata->fp = NULL;
mydata->is_writeable = 1;
mydata->is_brandnew = 1;
if (!alias_len || !alias) {
/* if we neither have an explicit nor an implicit alias, we use the filename */
phar_request_initialize(TSRMLS_C);
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
if (is_data) {
alias = NULL;
alias_len = 0;
register_alias = 0;
} else {
register_alias = 1;
phar_archive_data **fd_ptr;

if (alias && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
if (error) {
spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias);
}
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
if (pphar) {
*pphar = NULL;
}
return FAILURE;
}
}
mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
mydata->alias_len = alias ? alias_len : fname_len;
}
phar_request_initialize(TSRMLS_C);
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
if (register_alias) {
if (alias_len && alias) {
if (FAILURE == zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL)) {
if (options & REPORT_ERRORS) {
if (error) {
spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias);
}
}
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
if (pphar) {
*pphar = NULL;
}
return FAILURE;
}
}
Expand Down
3 changes: 3 additions & 0 deletions ext/phar/phar_object.c
Expand Up @@ -1157,6 +1157,9 @@ PHP_METHOD(Phar, __construct)
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"%s", error);
efree(error);
} else {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
"Phar creation or opening failed");
}
return;
}
Expand Down
25 changes: 21 additions & 4 deletions ext/phar/tar.c
Expand Up @@ -400,8 +400,8 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
phar_archive_data **fd_ptr;

myphar->is_temporary_alias = 0;
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void **)&fd_ptr)) {
if (SUCCESS != phar_free_alias(*fd_ptr, actual_alias, myphar->alias_len TSRMLS_CC)) {
if (error) {
spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname);
}
Expand All @@ -411,8 +411,25 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
}
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
} else {
myphar->alias = estrndup(myphar->fname, fname_len);
myphar->alias_len = fname_len;
phar_archive_data **fd_ptr;

if (alias_len) {
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
if (error) {
spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname);
}
zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len);
return FAILURE;
}
}
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
myphar->alias = estrndup(alias, alias_len);
myphar->alias_len = alias_len;
} else {
myphar->alias = estrndup(myphar->fname, fname_len);
myphar->alias_len = fname_len;
}
myphar->is_temporary_alias = 1;
}
if (pphar) {
Expand Down
46 changes: 46 additions & 0 deletions ext/phar/tests/alias_acrobatics.phpt
@@ -0,0 +1,46 @@
--TEST--
Phar: alias edge cases
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=0
--FILE--
<?php

$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar';
$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.phar';

$p = new Phar($fname);

$p->setAlias('foo');
$p['unused'] = 'hi';
try {
$a = new Phar($fname2, 0, 'foo');
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
copy($fname, $fname2);
echo "2\n";
try {
$a = new Phar($fname2);
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
try {
$b = new Phar($fname, 0, 'another');
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
?>
===DONE===
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar');
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar');
?>
--EXPECTF--
alias "foo" is already used for archive "%salias_acrobatics.phar" cannot be overloaded with "%salias_acrobatics.2.phar"
2
Cannot open archive "%salias_acrobatics.2.phar", alias is already in use by existing archive
alias "another" is already used for archive "%salias_acrobatics.phar" cannot be overloaded with "%salias_acrobatics.phar"
===DONE===
2 changes: 1 addition & 1 deletion ext/phar/tests/phar_setalias2.phpt
Expand Up @@ -47,5 +47,5 @@ __HALT_COMPILER();
hio
test
alias "test" is already used for archive "%sphar_setalias2.phar.php" and cannot be used for other archives
archive "%snope.phar" cannot be associated with alias "test", already in use
alias "test" is already used for archive "%sphar_setalias2.phar.php" cannot be overloaded with "%snope.phar"
===DONE===
46 changes: 46 additions & 0 deletions ext/phar/tests/tar/alias_acrobatics.phpt
@@ -0,0 +1,46 @@
--TEST--
Phar: alias edge cases
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=0
--FILE--
<?php

$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar';
$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.phar.tar';

$p = new Phar($fname);

$p->setAlias('foo');
$p['unused'] = 'hi';
try {
$a = new Phar($fname2, 0, 'foo');
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
copy($fname, $fname2);
echo "2\n";
try {
$a = new Phar($fname2);
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
try {
$b = new Phar($fname, 0, 'another');
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
?>
===DONE===
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.tar');
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.tar');
?>
--EXPECTF--
alias "foo" is already used for archive "%salias_acrobatics.phar.tar" cannot be overloaded with "%salias_acrobatics.2.phar.tar"
2
phar error: Unable to add tar-based phar "%salias_acrobatics.2.phar.tar", alias is already in use
alias "another" is already used for archive "%salias_acrobatics.phar.tar" cannot be overloaded with "%salias_acrobatics.phar.tar"
===DONE===
1 change: 1 addition & 0 deletions ext/phar/tests/zip/033.phpt
Expand Up @@ -22,6 +22,7 @@ try {
var_dump($phar['a.php']->isExecutable());
$phar['a.php']->chmod(0777);
copy($fname, $fname2);
$phar->setAlias('unused');
$phar2 = new Phar($fname2);
var_dump($phar2['a.php']->isExecutable());
$phar['a.php']->chmod(0666);
Expand Down
46 changes: 46 additions & 0 deletions ext/phar/tests/zip/alias_acrobatics.phpt
@@ -0,0 +1,46 @@
--TEST--
Phar: alias edge cases
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=0
--FILE--
<?php

$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.zip';
$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.phar.zip';

$p = new Phar($fname);

$p->setAlias('foo');
$p['unused'] = 'hi';
try {
$a = new Phar($fname2, 0, 'foo');
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
copy($fname, $fname2);
echo "2\n";
try {
$a = new Phar($fname2);
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
try {
$b = new Phar($fname, 0, 'another');
} catch (Exception $e) {
echo $e->getMessage(),"\n";
}
?>
===DONE===
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip');
unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip');
?>
--EXPECTF--
alias "foo" is already used for archive "%salias_acrobatics.phar.zip" cannot be overloaded with "%salias_acrobatics.2.phar.zip"
2
phar error: Unable to add zip-based phar "%salias_acrobatics.2.phar.zip" with implicit alias, alias is already in use
alias "another" is already used for archive "%salias_acrobatics.phar.zip" cannot be overloaded with "%salias_acrobatics.phar.zip"
===DONE===
10 changes: 5 additions & 5 deletions ext/phar/tests/zip/badalias.phpt
Expand Up @@ -17,9 +17,9 @@ echo $ee->getMessage(), "\n";
?>
===DONE===
--EXPECTF--
phar error: invalid alias in zip-based phar "%sbadalias1.phar.zip"
phar error: invalid alias in zip-based phar "%sbadalias2.phar.zip"
phar error: invalid alias in zip-based phar "%sbadalias3.phar.zip"
phar error: invalid alias in zip-based phar "%sbadalias4.phar.zip"
phar error: invalid alias in zip-based phar "%sbadalias5.phar.zip"
phar error: invalid alias "hi/there" in zip-based phar "%sbadalias1.phar.zip"
phar error: invalid alias "hi\there" in zip-based phar "%sbadalias2.phar.zip"
phar error: invalid alias "hi\there" in zip-based phar "%sbadalias3.phar.zip"
phar error: invalid alias "hi;there" in zip-based phar "%sbadalias4.phar.zip"
phar error: invalid alias "hi:there" in zip-based phar "%sbadalias5.phar.zip"
===DONE===
6 changes: 6 additions & 0 deletions ext/phar/util.c
Expand Up @@ -1032,6 +1032,12 @@ int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len, ch
*archive = *fd_ptr;
fd = *fd_ptr;
if (alias && alias_len) {
if (!fd->is_temporary_alias && (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len))) {
if (error) {
spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, (*fd_ptr)->fname, fname);
}
return FAILURE;
}
if (fd->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), fd->alias, fd->alias_len, (void**)&fd_ptr)) {
zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), fd->alias, fd->alias_len);
}
Expand Down

0 comments on commit 82dc039

Please sign in to comment.