From 4b035dae5f66354928183c593facb08f98358be8 Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Thu, 22 May 2008 06:33:09 +0000 Subject: [PATCH] major fixes * found felipe's segfault in util.c and fixed the segfault (3 tests fail due to odd behavior of . and .. on this machine) * fixed serious flaws in the setting/resetting of is_data - now it works properly. Assume all new PharData are tar-based, and allow passing Phar::ZIP to PharData constructor to override this * fix broken earlier commit, introduced segfault that broke 20 tests here --- ext/phar/phar.c | 8 ++++--- ext/phar/phar_object.c | 50 +++++++++++++++++++++++++++++++----------- ext/phar/tar.c | 7 ++++++ ext/phar/util.c | 3 +++ ext/phar/zip.c | 6 +++++ 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index f432c06926..0b595a9c8f 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -406,7 +406,6 @@ int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_len, int } } } - phar->is_data = is_data && (phar->is_tar || phar->is_zip); if (pphar) { *pphar = phar; } @@ -1033,12 +1032,12 @@ check_file: } 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 + /* assume zip-based phar */ return phar_open_or_create_zip(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC); } 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 + /* assume tar-based phar */ return phar_open_or_create_tar(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC); } @@ -1140,6 +1139,9 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a if (is_data) { alias = NULL; alias_len = 0; + mydata->is_data = 1; + /* assume tar format, PharData can specify other */ + mydata->is_tar = 1; } else { phar_archive_data **fd_ptr; diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 2a14d61387..f7f4f80728 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1102,7 +1102,7 @@ static spl_other_handler phar_spl_foreign_handler = { /* {{{ proto void Phar::__construct(string fname [, int flags [, string alias]]) * Construct a Phar archive object - * {{{ proto void PharData::__construct(string fname [, int flags [, string alias]]) + * {{{ proto void PharData::__construct(string fname [[, int flags [, string alias]], int file format = Phar::TAR]) * Construct a PharData archive object */ PHP_METHOD(Phar, __construct) @@ -1112,22 +1112,13 @@ PHP_METHOD(Phar, __construct) #else char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname, *objname; int fname_len, alias_len = 0, arch_len, entry_len, is_data; - long flags = 0; + long flags = 0, format = 0; phar_archive_object *phar_obj; phar_archive_data *phar_data; zval *zobj = getThis(), arg1, arg2; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) { - return; - } - phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - if (phar_obj->arc.archive) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice"); - return; - } - PHAR_STR(phar_obj->std.ce->name, objname); if (!strncmp(objname, "PharData", 8)) { @@ -1136,6 +1127,21 @@ PHP_METHOD(Phar, __construct) is_data = 0; } + if (is_data) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) { + return; + } + } + + if (phar_obj->arc.archive) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice"); + return; + } + if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2 TSRMLS_CC)) { /* use arch (the basename for the archive) for fname instead of fname */ /* this allows support for RecursiveDirectoryIterator of subdirectories */ @@ -1175,11 +1181,26 @@ PHP_METHOD(Phar, __construct) return; } + if (is_data && phar_data->is_tar && phar_data->is_brandnew && format == PHAR_FORMAT_ZIP) { + phar_data->is_zip = 1; + phar_data->is_tar = 0; + } if (fname == arch) { efree(arch); fname = save_fname; } + if ((is_data && !phar_data->is_data) || (!is_data && phar_data->is_data)) { + if (is_data) { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, + "PharData class can only be used for non-executable tar and zip archives"); + } else { + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, + "Phar class can only be used for executable tar and zip archives"); + } + efree(entry); + return; + } is_data = phar_data->is_data; ++(phar_data->refcount); phar_obj->arc.archive = phar_data; @@ -1819,7 +1840,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c char *error; const char *pcr_error; int ext_len = ext ? strlen(ext) : 0; - phar_archive_data **pphar; + phar_archive_data **pphar = NULL; if (!ext) { if (phar->is_zip) { @@ -1887,6 +1908,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c basepath = estrndup(oldpath, strlen(oldpath) - strlen(oldname)); phar->fname_len = spprintf(&newpath, 0, "%s%s", basepath, newname); phar->fname = newpath; + phar->ext = newpath + phar->fname_len - strlen(ext) - 1; efree(basepath); efree(newname); @@ -1901,6 +1923,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c phar->fp = NULL; phar_destroy_phar_data(phar TSRMLS_CC); phar = *pphar; + phar->refcount++; newpath = oldpath; goto its_ok; } @@ -1938,7 +1961,7 @@ its_ok: phar->alias_len = 0; } - if (SUCCESS != zend_hash_update(&(PHAR_GLOBALS->phar_fname_map), newpath, phar->fname_len, (void*)&phar, sizeof(phar_archive_data*), NULL)) { + if ((!pphar || phar == *pphar) && SUCCESS != zend_hash_update(&(PHAR_GLOBALS->phar_fname_map), newpath, phar->fname_len, (void*)&phar, sizeof(phar_archive_data*), NULL)) { efree(oldpath); zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to add newly converted phar \"%s\" to the list of phars", phar->fname); return NULL; @@ -4416,6 +4439,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, flags) ZEND_ARG_INFO(0, alias) + ZEND_ARG_INFO(0, fileformat) ZEND_END_ARG_INFO(); static diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 802f6149db..32d2261db5 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -141,6 +141,7 @@ int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_l if (phar->is_brandnew) { phar->is_tar = 1; + phar->is_zip = 0; phar->internal_file_start = 0; return SUCCESS; } @@ -422,6 +423,12 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i #endif myphar->fname_len = fname_len; p = strrchr(myphar->fname, '/'); + + if (zend_hash_exists(&(myphar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) { + myphar->is_data = 0; + } else { + myphar->is_data = 1; + } if (p) { myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p); if (myphar->ext == p) { diff --git a/ext/phar/util.c b/ext/phar/util.c index bc6ccaaa78..7d8ce5e0eb 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1172,6 +1172,9 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in return NULL; } if (is_dir) { + if (!path_len || path_len == 1) { + return NULL; + } path_len--; } if (SUCCESS == zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) { diff --git a/ext/phar/zip.c b/ext/phar/zip.c index d266b53dce..6cd4a5a722 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -443,6 +443,11 @@ foundit: zend_hash_add(&mydata->manifest, entry.filename, entry.filename_len, (void *)&entry,sizeof(phar_entry_info), NULL); } mydata->fp = fp; + if (zend_hash_exists(&(mydata->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) { + mydata->is_data = 0; + } else { + mydata->is_data = 1; + } zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL); if (actual_alias) { phar_archive_data **fd_ptr; @@ -522,6 +527,7 @@ int phar_open_or_create_zip(char *fname, int fname_len, char *alias, int alias_l if (phar->is_brandnew) { phar->internal_file_start = 0; phar->is_zip = 1; + phar->is_tar = 0; return SUCCESS; } -- 2.40.0