- MFB 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
This commit is contained in:
Steph Fox 2008-05-24 14:18:31 +00:00
parent 7efb792fe8
commit 76a9ec377b
5 changed files with 65 additions and 16 deletions

View file

@ -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) { if (pphar) {
*pphar = phar; *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)) { 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); 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)) { 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); 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) { if (is_data) {
alias = NULL; alias = NULL;
alias_len = 0; alias_len = 0;
mydata->is_data = 1;
/* assume tar format, PharData can specify other */
mydata->is_tar = 1;
} else { } else {
phar_archive_data **fd_ptr; phar_archive_data **fd_ptr;

View file

@ -1120,7 +1120,7 @@ static spl_other_handler phar_spl_foreign_handler = {
/* {{{ proto void Phar::__construct(string fname [, int flags [, string alias]]) /* {{{ proto void Phar::__construct(string fname [, int flags [, string alias]])
* Construct a Phar archive object * 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 * Construct a PharData archive object
*/ */
PHP_METHOD(Phar, __construct) PHP_METHOD(Phar, __construct)
@ -1130,22 +1130,13 @@ PHP_METHOD(Phar, __construct)
#else #else
char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname, *objname; char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname, *objname;
int fname_len, alias_len = 0, arch_len, entry_len, is_data; 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_object *phar_obj;
phar_archive_data *phar_data; phar_archive_data *phar_data;
zval *zobj = getThis(), arg1, arg2; 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); 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); PHAR_STR(phar_obj->std.ce->name, objname);
if (!strncmp(objname, "PharData", 8)) { if (!strncmp(objname, "PharData", 8)) {
@ -1154,6 +1145,21 @@ PHP_METHOD(Phar, __construct)
is_data = 0; 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)) { 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 */ /* use arch (the basename for the archive) for fname instead of fname */
/* this allows support for RecursiveDirectoryIterator of subdirectories */ /* this allows support for RecursiveDirectoryIterator of subdirectories */
@ -1193,11 +1199,28 @@ PHP_METHOD(Phar, __construct)
return; 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) { if (fname == arch) {
efree(arch); efree(arch);
fname = save_fname; 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; is_data = phar_data->is_data;
++(phar_data->refcount); ++(phar_data->refcount);
phar_obj->arc.archive = phar_data; phar_obj->arc.archive = phar_data;
@ -1844,7 +1867,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
char *error; char *error;
const char *pcr_error; const char *pcr_error;
int ext_len = ext ? strlen(ext) : 0; int ext_len = ext ? strlen(ext) : 0;
phar_archive_data **pphar; phar_archive_data **pphar = NULL;
if (!ext) { if (!ext) {
if (phar->is_zip) { if (phar->is_zip) {
@ -1912,6 +1935,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
basepath = estrndup(oldpath, strlen(oldpath) - strlen(oldname)); basepath = estrndup(oldpath, strlen(oldpath) - strlen(oldname));
phar->fname_len = spprintf(&newpath, 0, "%s%s", basepath, newname); phar->fname_len = spprintf(&newpath, 0, "%s%s", basepath, newname);
phar->fname = newpath; phar->fname = newpath;
phar->ext = newpath + phar->fname_len - strlen(ext) - 1;
efree(basepath); efree(basepath);
efree(newname); efree(newname);
@ -1926,6 +1950,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
phar->fp = NULL; phar->fp = NULL;
phar_destroy_phar_data(phar TSRMLS_CC); phar_destroy_phar_data(phar TSRMLS_CC);
phar = *pphar; phar = *pphar;
phar->refcount++;
newpath = oldpath; newpath = oldpath;
goto its_ok; goto its_ok;
} }
@ -1963,7 +1988,7 @@ its_ok:
phar->alias_len = 0; 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); 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); 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; return NULL;
@ -4451,6 +4476,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1)
ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, flags) ZEND_ARG_INFO(0, flags)
ZEND_ARG_INFO(0, alias) ZEND_ARG_INFO(0, alias)
ZEND_ARG_INFO(0, fileformat)
ZEND_END_ARG_INFO(); ZEND_END_ARG_INFO();
static static

View file

@ -141,6 +141,7 @@ int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_l
if (phar->is_brandnew) { if (phar->is_brandnew) {
phar->is_tar = 1; phar->is_tar = 1;
phar->is_zip = 0;
phar->internal_file_start = 0; phar->internal_file_start = 0;
return SUCCESS; return SUCCESS;
} }
@ -422,6 +423,13 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
#endif #endif
myphar->fname_len = fname_len; myphar->fname_len = fname_len;
p = strrchr(myphar->fname, '/'); 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) { if (p) {
myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p); myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p);
if (myphar->ext == p) { if (myphar->ext == p) {

View file

@ -1171,9 +1171,14 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in
if (!phar->manifest.arBuckets) { if (!phar->manifest.arBuckets) {
return NULL; return NULL;
} }
if (is_dir) { if (is_dir) {
if (!path_len || path_len == 1) {
return NULL;
}
path_len--; path_len--;
} }
if (SUCCESS == zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) { if (SUCCESS == zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) {
if (entry->is_deleted) { if (entry->is_deleted) {
/* entry is deleted, but has not been flushed to disk yet */ /* entry is deleted, but has not been flushed to disk yet */

View file

@ -443,6 +443,13 @@ foundit:
zend_hash_add(&mydata->manifest, entry.filename, entry.filename_len, (void *)&entry,sizeof(phar_entry_info), NULL); zend_hash_add(&mydata->manifest, entry.filename, entry.filename_len, (void *)&entry,sizeof(phar_entry_info), NULL);
} }
mydata->fp = fp; 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); zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
if (actual_alias) { if (actual_alias) {
phar_archive_data **fd_ptr; phar_archive_data **fd_ptr;
@ -522,6 +529,7 @@ int phar_open_or_create_zip(char *fname, int fname_len, char *alias, int alias_l
if (phar->is_brandnew) { if (phar->is_brandnew) {
phar->internal_file_start = 0; phar->internal_file_start = 0;
phar->is_zip = 1; phar->is_zip = 1;
phar->is_tar = 0;
return SUCCESS; return SUCCESS;
} }