Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 57 additions & 33 deletions ext/phar/phar.c
Original file line number Diff line number Diff line change
Expand Up @@ -1302,8 +1302,14 @@ static zend_result phar_parse_pharfile(php_stream *fp, const char *fname, size_t
/**
* Create or open a phar for writing
*/
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
{
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 5, 6) zend_result phar_open_or_create_filename(
zend_string *fname,
/* copyable & hash update */ zend_string *alias,
bool is_data,
uint32_t options,
phar_archive_data** pphar,
char **error
) {
const char *ext_str, *z;
char *my_error;
size_t ext_len;
Expand All @@ -1327,8 +1333,10 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(ze
}
return FAILURE;
}
check_file:
if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, is_data, options, test, &my_error) == SUCCESS) {
check_file:;
const char *alias_cstr = alias ? ZSTR_VAL(alias) : NULL;
size_t alias_len = alias ? ZSTR_LEN(alias) : 0;
if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias_cstr, alias_len, is_data, options, test, &my_error) == SUCCESS) {
*pphar = *test;

if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) {
Expand All @@ -1354,22 +1362,27 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(ze

if (ext_len > 3 && (z = memchr(ext_str, 'z', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ip", 2)) {
/* assume zip-based phar */
return phar_open_or_create_zip(fname, alias, alias_len, is_data, options, pphar, error);
return phar_open_or_create_zip(fname, alias, is_data, options, pphar, error);
}

if (ext_len > 3 && (z = memchr(ext_str, 't', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ar", 2)) {
/* assume tar-based phar */
return phar_open_or_create_tar(fname, alias, alias_len, is_data, options, pphar, error);
return phar_open_or_create_tar(fname, alias, is_data, options, pphar, error);
}

return phar_create_or_parse_filename(fname, alias, alias_len, is_data, options, pphar, error);
return phar_create_or_parse_filename(fname, alias, is_data, options, pphar, error);
}
/* }}} */

static zend_result phar_open_from_fp(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error);
static zend_result phar_open_from_fp(php_stream* fp, const char *fname, size_t fname_len, /* copyable & hash update */ zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error);

ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
{
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 5, 6) zend_result phar_create_or_parse_filename(
zend_string *fname,
/* copyable & hash update */ zend_string *alias,
bool is_data,
uint32_t options,
phar_archive_data** pphar,
char **error
) {
php_stream *fp;
zend_string *actual = NULL;
zend_string *save_fname = fname;
Expand All @@ -1387,7 +1400,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z
}

if (fp) {
if (phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, options, pphar, error) == SUCCESS) {
if (phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, options, pphar, error) == SUCCESS) {
if ((*pphar)->is_data || !PHAR_G(readonly)) {
(*pphar)->is_writeable = 1;
}
Expand Down Expand Up @@ -1458,15 +1471,14 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z

if (is_data) {
alias = NULL;
alias_len = 0;
mydata->is_data = 1;
/* assume tar format, PharData can specify other */
mydata->is_tar = 1;
} else {
if (alias) {
const phar_archive_data *fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len);
const phar_archive_data *fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), alias);
if (fd_ptr && SUCCESS != phar_free_alias(fd_ptr)) {
spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", ZSTR_VAL(mydata->fname), alias);
spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", ZSTR_VAL(mydata->fname), ZSTR_VAL(alias));

zend_hash_del(&(PHAR_G(phar_fname_map)), mydata->fname);

Expand All @@ -1477,14 +1489,14 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z
}

ZEND_ASSERT(!mydata->is_persistent);
mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(ZSTR_VAL(mydata->fname), ZSTR_LEN(mydata->fname));
mydata->alias_len = alias ? alias_len : ZSTR_LEN(mydata->fname);
mydata->alias = alias ? estrndup(ZSTR_VAL(alias), ZSTR_LEN(alias)) : estrndup(ZSTR_VAL(mydata->fname), ZSTR_LEN(mydata->fname));
mydata->alias_len = alias ? ZSTR_LEN(alias) : ZSTR_LEN(mydata->fname);
}

if (alias_len && alias) {
if (NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata)) {
if (alias) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note there is subtle change of behaviour throughout. i.e. empty values are potentially accepted ?

if (NULL == zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), alias, mydata)) {
if (options & REPORT_ERRORS) {
spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", ZSTR_VAL(fname), alias);
spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", ZSTR_VAL(fname), ZSTR_VAL(alias));
}

zend_hash_del(&(PHAR_G(phar_fname_map)), mydata->fname);
Expand All @@ -1498,7 +1510,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z
*pphar = mydata;
return SUCCESS;
}
/* }}}*/

/**
* Return an already opened filename.
Expand All @@ -1507,8 +1518,14 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z
* that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS
* or FAILURE is returned and pphar is set to a pointer to the phar's manifest
*/
zend_result phar_open_from_filename(char *fname, size_t fname_len, const zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
{
zend_result phar_open_from_filename(
char *fname,
size_t fname_len,
/* copyable & hash update */ zend_string *alias,
uint32_t options,
phar_archive_data** pphar,
char **error
) {
php_stream *fp;
zend_string *actual;
bool is_data = false;
Expand Down Expand Up @@ -1551,23 +1568,29 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, const zend_st
fname_len = ZSTR_LEN(actual);
}

zend_result ret = phar_open_from_fp(fp, fname, fname_len, alias_cstr, alias_len, options, pphar, error);
zend_result ret = phar_open_from_fp(fp, fname, fname_len, alias, options, pphar, error);

if (actual) {
zend_string_release_ex(actual, 0);
}

return ret;
}
/* }}}*/

/**
* Scan an open fp for the required __HALT_COMPILER(); ?> token and verify
* that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS
* or FAILURE is returned and pphar is set to a pointer to the phar's manifest
*/
static zend_result phar_open_from_fp(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
{
static zend_result phar_open_from_fp(
php_stream* fp,
const char *fname,
size_t fname_len,
/* copyable & hash update */ zend_string *alias,
uint32_t options,
phar_archive_data** pphar,
char **error
) {
static const char token[] = "__HALT_COMPILER();";
static const char zip_magic[] = "PK\x03\x04";
static const char gz_magic[] = "\x1f\x8b\x08";
Expand Down Expand Up @@ -1718,20 +1741,22 @@ static zend_result phar_open_from_fp(php_stream* fp, const char *fname, size_t f

if (!memcmp(pos, zip_magic, 4)) {
php_stream_seek(fp, 0, SEEK_END);
return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error);
return phar_parse_zipfile(fp, fname, fname_len, alias, pphar, error);
}

if (got >= 512) {
if (phar_is_tar(pos, fname)) {
php_stream_rewind(fp);
return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, compression, error);
return phar_parse_tarfile(fp, fname, fname_len, alias, pphar, compression, error);
}
}
}

if (got > 0 && (pos = php_memnistr(buffer, token, tokenlen, buffer + got + sizeof(token))) != NULL) {
halt_offset += (pos - buffer); /* no -tokenlen+tokenlen here */
return phar_parse_pharfile(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, compression, error);
const char *alias_cstr = alias ? ZSTR_VAL(alias) : NULL;
size_t alias_len = alias ? ZSTR_LEN(alias) : 0;
return phar_parse_pharfile(fp, fname, fname_len, alias_cstr, alias_len, halt_offset, pphar, compression, error);
}

halt_offset += got;
Expand All @@ -1740,7 +1765,6 @@ static zend_result phar_open_from_fp(php_stream* fp, const char *fname, size_t f

MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (__HALT_COMPILER(); not found)")
}
/* }}} */

/*
* given the location of the file extension and the start of the file path,
Expand Down Expand Up @@ -2254,7 +2278,7 @@ zend_string* phar_split_fname(const char *filename, size_t filename_len, zend_st
* Invoked when a user calls Phar::mapPhar() from within an executing .phar
* to set up its manifest directly
*/
ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(const zend_string *alias, char **error) /* {{{ */
ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(/* copyable & hash update */ zend_string *alias, char **error) /* {{{ */
{
*error = NULL;

Expand Down Expand Up @@ -2296,7 +2320,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(const zen
fname = actual;
}

zend_result ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias_cstr, alias_len, REPORT_ERRORS, NULL, error);
zend_result ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, REPORT_ERRORS, NULL, error);

if (actual) {
zend_string_release_ex(actual, 0);
Expand Down
16 changes: 8 additions & 8 deletions ext/phar/phar_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,10 +406,10 @@ void phar_object_init(void);
void phar_destroy_phar_data(phar_archive_data *phar);

ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip);
zend_result phar_open_from_filename(char *fname, size_t fname_len, const zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(const zend_string *alias, char **error);
zend_result phar_open_from_filename(char *fname, size_t fname_len, /* copyable & hash update */ zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 5, 6) zend_result phar_open_or_create_filename(zend_string *fname, /* copyable & hash update */ zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 5, 6) zend_result phar_create_or_parse_filename(zend_string *fname, /* copyable & hash update */ zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(/* copyable & hash update */ zend_string *alias, char **error);
zend_result phar_free_alias(const phar_archive_data *phar);
phar_archive_data* phar_get_archive(const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error);
zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, const char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error);
Expand Down Expand Up @@ -445,13 +445,13 @@ zend_result phar_copy_on_write(phar_archive_data **pphar);

/* tar functions in tar.c */
bool phar_is_tar(const char *buf, const char *fname);
zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, /* copyable & hash update */ zend_string *alias, phar_archive_data** pphar, uint32_t compression, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 5, 6) zend_result phar_open_or_create_tar(zend_string *fname, /* copyable & hash update */ zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error);

/* zip functions in zip.c */
zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_len, /* copyable & hash update */ zend_string *alias, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 5, 6) zend_result phar_open_or_create_zip(zend_string *fname, /* copyable & hash update */ zend_string *alias, bool is_data, uint32_t options, phar_archive_data** pphar, char **error);
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error);

#ifdef PHAR_MAIN
Expand Down
10 changes: 5 additions & 5 deletions ext/phar/phar_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,8 @@ static const spl_other_handler phar_spl_foreign_handler = {
PHP_METHOD(Phar, __construct)
{
zend_string *fname;
char *alias = NULL, *error;
size_t alias_len = 0;
zend_string *alias;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you probably need to initialise alias since it is optional.

char *error;
bool is_data;
zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
zend_long format = 0;
Expand All @@ -1099,11 +1099,11 @@ PHP_METHOD(Phar, __construct)
is_data = instanceof_function(Z_OBJCE_P(ZEND_THIS), phar_ce_data);

if (is_data) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ls!l", &fname, &flags, &alias, &alias_len, &format) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|lS!l", &fname, &flags, &alias, &format) == FAILURE) {
RETURN_THROWS();
}
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ls!", &fname, &flags, &alias, &alias_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|lS!", &fname, &flags, &alias) == FAILURE) {
RETURN_THROWS();
}
}
Expand All @@ -1122,7 +1122,7 @@ PHP_METHOD(Phar, __construct)
fname = arch;
}

zend_result phar_status = phar_open_or_create_filename(fname, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error);
zend_result phar_status = phar_open_or_create_filename(fname, alias, is_data, REPORT_ERRORS, &phar_data, &error);

if (arch) {
zend_string_release_ex(arch, false);
Expand Down
2 changes: 1 addition & 1 deletion ext/phar/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const
php_url_free(resource);
return NULL;
}
if (phar_open_or_create_filename(resource->host, NULL, 0, 0, options, &phar, &error) == FAILURE)
if (phar_open_or_create_filename(resource->host, NULL, 0, options, &phar, &error) == FAILURE)
{
if (error) {
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
Expand Down
35 changes: 23 additions & 12 deletions ext/phar/tar.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,16 @@ bool phar_is_tar(const char *buf, const char *fname) /* {{{ */
}
/* }}} */

ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */
{
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 5, 6) zend_result phar_open_or_create_tar(
zend_string *fname,
/* copyable & hash update */ zend_string *alias,
bool is_data,
uint32_t options,
phar_archive_data** pphar,
char **error
) {
phar_archive_data *phar;
zend_result ret = phar_create_or_parse_filename(fname, alias, alias_len, is_data, options, &phar, error);
zend_result ret = phar_create_or_parse_filename(fname, alias, is_data, options, &phar, error);

if (FAILURE == ret) {
return FAILURE;
Expand All @@ -153,7 +159,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_st
spprintf(error, 4096, "phar tar error: \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a tar-based phar", ZSTR_VAL(fname));
return FAILURE;
}
/* }}} */

static zend_result phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp) /* {{{ */
{
Expand Down Expand Up @@ -197,8 +202,15 @@ static zend_result phar_tar_process_metadata(phar_entry_info *entry, php_stream
}
/* }}} */

zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */
{
zend_result phar_parse_tarfile(
php_stream* fp,
const char *fname,
size_t fname_len,
/* copyable & hash update */ zend_string *alias,
phar_archive_data** pphar,
uint32_t compression,
char **error
) {
char buf[512], *actual_alias = NULL, *p;
phar_entry_info entry = {0};
size_t pos = 0, read, totalsize;
Expand Down Expand Up @@ -674,8 +686,8 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l

zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), actual_alias, myphar->alias_len, myphar);
} else {
if (alias_len) {
phar_archive_data *fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len);
if (alias) {
phar_archive_data *fd_ptr = zend_hash_find_ptr(&(PHAR_G(phar_alias_map)), alias);
if (fd_ptr) {
if (SUCCESS != phar_free_alias(fd_ptr)) {
if (error) {
Expand All @@ -685,9 +697,9 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l
return FAILURE;
}
}
zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, myphar);
myphar->alias = pestrndup(alias, alias_len, myphar->is_persistent);
myphar->alias_len = alias_len;
zend_hash_add_ptr(&(PHAR_G(phar_alias_map)), alias, myphar);
myphar->alias = pestrndup(ZSTR_VAL(alias), ZSTR_LEN(alias), myphar->is_persistent);
myphar->alias_len = ZSTR_LEN(alias);
} else {
myphar->alias = pestrndup(ZSTR_VAL(myphar->fname), ZSTR_LEN(myphar->fname), myphar->is_persistent);
myphar->alias_len = ZSTR_LEN(myphar->fname);
Expand All @@ -702,7 +714,6 @@ zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_l

return SUCCESS;
}
/* }}} */

struct _phar_pass_tar_info {
php_stream *old;
Expand Down
Loading
Loading