mirror of
https://github.com/php/php-src.git
synced 2025-08-19 17:04:47 +02:00
fix stat of directory in tar/zip
improve phar recognition of tar/zip-based phars in phar_compile_file fix segfault in Phar::webPhar() with invalid redirect add Phar->isTar()/isZip()/isPhar() to determine internal file format fix creation of tar-based phars from filename in some circumstances fix read of corrupted file contents from a tar if the tar had been opened readonly and then modified ensure directories are marked with is_dir in tar file format entries copy fp_refcount logic into phar_tar_flush() from phar_flush() fix segfault when flushing a tar with a new stub/alias
This commit is contained in:
parent
ff1c8b2beb
commit
8a46146f37
3 changed files with 91 additions and 37 deletions
|
@ -4027,6 +4027,20 @@ static void phar_dostat(phar_archive_data *phar, phar_entry_info *data, php_stre
|
||||||
ssb->sb.st_mtime = data->timestamp;
|
ssb->sb.st_mtime = data->timestamp;
|
||||||
ssb->sb.st_atime = data->timestamp;
|
ssb->sb.st_atime = data->timestamp;
|
||||||
ssb->sb.st_ctime = data->timestamp;
|
ssb->sb.st_ctime = data->timestamp;
|
||||||
|
#endif
|
||||||
|
} else if (!is_dir && data->is_dir && (data->is_tar || data->is_zip)) {
|
||||||
|
ssb->sb.st_size = 0;
|
||||||
|
ssb->sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
|
||||||
|
ssb->sb.st_mode |= S_IFDIR; /* regular directory */
|
||||||
|
/* timestamp is just the timestamp when this was added to the phar */
|
||||||
|
#ifdef NETWARE
|
||||||
|
ssb->sb.st_mtime.tv_sec = data->timestamp;
|
||||||
|
ssb->sb.st_atime.tv_sec = data->timestamp;
|
||||||
|
ssb->sb.st_ctime.tv_sec = data->timestamp;
|
||||||
|
#else
|
||||||
|
ssb->sb.st_mtime = data->timestamp;
|
||||||
|
ssb->sb.st_atime = data->timestamp;
|
||||||
|
ssb->sb.st_ctime = data->timestamp;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ssb->sb.st_size = 0;
|
ssb->sb.st_size = 0;
|
||||||
|
@ -4719,14 +4733,16 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type
|
||||||
char *fname = NULL;
|
char *fname = NULL;
|
||||||
int fname_len, failed;
|
int fname_len, failed;
|
||||||
zend_op_array *(*save)(zend_file_handle *file_handle, int type TSRMLS_DC);
|
zend_op_array *(*save)(zend_file_handle *file_handle, int type TSRMLS_DC);
|
||||||
|
phar_archive_data *phar;
|
||||||
|
|
||||||
save = zend_compile_file; /* restore current handler or we cause trouble */
|
save = zend_compile_file; /* restore current handler or we cause trouble */
|
||||||
zend_compile_file = phar_orig_compile_file;
|
zend_compile_file = phar_orig_compile_file;
|
||||||
|
|
||||||
fname = zend_get_executed_filename(TSRMLS_C);
|
fname = zend_get_executed_filename(TSRMLS_C);
|
||||||
fname_len = strlen(fname);
|
fname_len = strlen(fname);
|
||||||
if (fname_len == sizeof("[no active file]")-1 && !strncmp(fname, "[no active file]", fname_len)) {
|
if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, ":\\")) {
|
||||||
if (strstr(file_handle->filename, ".phar.zip") && !strstr(file_handle->filename, ":\\")) {
|
if (SUCCESS == phar_open_filename(file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
|
||||||
|
if (phar->is_zip || phar->is_tar) {
|
||||||
/* zip-based phar */
|
/* zip-based phar */
|
||||||
spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
|
spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
|
||||||
file_handle->type = ZEND_HANDLE_FILENAME;
|
file_handle->type = ZEND_HANDLE_FILENAME;
|
||||||
|
@ -4737,16 +4753,6 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type
|
||||||
}
|
}
|
||||||
goto skip_phar;
|
goto skip_phar;
|
||||||
}
|
}
|
||||||
if (strstr(file_handle->filename, ".phar.tar") && !strstr(file_handle->filename, ":\\")) {
|
|
||||||
/* tar-based phar */
|
|
||||||
spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
|
|
||||||
file_handle->type = ZEND_HANDLE_FILENAME;
|
|
||||||
file_handle->free_filename = 1;
|
|
||||||
file_handle->filename = name;
|
|
||||||
if (file_handle->opened_path) {
|
|
||||||
efree(file_handle->opened_path);
|
|
||||||
}
|
|
||||||
goto skip_phar;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||||
|
|
|
@ -382,7 +382,7 @@ PHP_METHOD(Phar, webPhar)
|
||||||
if (strstr(fname, "://")) {
|
if (strstr(fname, "://")) {
|
||||||
char *arch, *entry;
|
char *arch, *entry;
|
||||||
int arch_len, entry_len;
|
int arch_len, entry_len;
|
||||||
phar_archive_data *phar;
|
phar_archive_data *mphar;
|
||||||
|
|
||||||
/* running within a zip-based phar, acquire the actual name */
|
/* running within a zip-based phar, acquire the actual name */
|
||||||
if (SUCCESS != phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
|
if (SUCCESS != phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
|
||||||
|
@ -395,10 +395,10 @@ PHP_METHOD(Phar, webPhar)
|
||||||
entry = fname;
|
entry = fname;
|
||||||
fname = arch;
|
fname = arch;
|
||||||
fname_len = arch_len;
|
fname_len = arch_len;
|
||||||
if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &phar, 0 TSRMLS_CC) && phar && (phar->is_zip || phar->is_tar)) {
|
if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &mphar, 0 TSRMLS_CC) && mphar && (phar->is_zip || phar->is_tar)) {
|
||||||
efree(arch);
|
efree(arch);
|
||||||
fname = phar->fname;
|
fname = mphar->fname;
|
||||||
fname_len = phar->fname_len;
|
fname_len = mphar->fname_len;
|
||||||
} else {
|
} else {
|
||||||
efree(arch);
|
efree(arch);
|
||||||
fname = entry;
|
fname = entry;
|
||||||
|
@ -476,7 +476,6 @@ PHP_METHOD(Phar, webPhar)
|
||||||
/* check for "rewrite" urls */
|
/* check for "rewrite" urls */
|
||||||
if (SUCCESS == zend_hash_find(Z_ARRVAL_P(rewrites), entry, entry_len+1, (void **) &fd_ptr)) {
|
if (SUCCESS == zend_hash_find(Z_ARRVAL_P(rewrites), entry, entry_len+1, (void **) &fd_ptr)) {
|
||||||
if (IS_STRING != Z_TYPE_PP(fd_ptr)) {
|
if (IS_STRING != Z_TYPE_PP(fd_ptr)) {
|
||||||
phar_entry_delref(phar TSRMLS_CC);
|
|
||||||
#ifdef PHP_WIN32
|
#ifdef PHP_WIN32
|
||||||
efree(fname);
|
efree(fname);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1218,6 +1217,39 @@ PHP_METHOD(Phar, count)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto bool Phar::isTar()
|
||||||
|
* Returns true if the phar archive is based on the tar file format
|
||||||
|
*/
|
||||||
|
PHP_METHOD(Phar, isTar)
|
||||||
|
{
|
||||||
|
PHAR_ARCHIVE_OBJECT();
|
||||||
|
|
||||||
|
RETURN_BOOL(phar_obj->arc.archive->is_tar);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto bool Phar::isZip()
|
||||||
|
* Returns true if the phar archive is based on the Zip file format
|
||||||
|
*/
|
||||||
|
PHP_METHOD(Phar, isZip)
|
||||||
|
{
|
||||||
|
PHAR_ARCHIVE_OBJECT();
|
||||||
|
|
||||||
|
RETURN_BOOL(phar_obj->arc.archive->is_zip);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto bool Phar::isPhar()
|
||||||
|
* Returns true if the phar archive is based on the phar file format
|
||||||
|
*/
|
||||||
|
PHP_METHOD(Phar, isPhar)
|
||||||
|
{
|
||||||
|
PHAR_ARCHIVE_OBJECT();
|
||||||
|
|
||||||
|
RETURN_BOOL(!phar_obj->arc.archive->is_tar && !phar_obj->arc.archive->is_zip);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ proto bool Phar::delete(string file)
|
/* {{{ proto bool Phar::delete(string file)
|
||||||
* Delete a file from within the Phar
|
* Delete a file from within the Phar
|
||||||
*/
|
*/
|
||||||
|
@ -2217,8 +2249,8 @@ PHP_METHOD(PharFileInfo, __destruct)
|
||||||
{
|
{
|
||||||
PHAR_ENTRY_OBJECT();
|
PHAR_ENTRY_OBJECT();
|
||||||
|
|
||||||
if (entry_obj->ent.entry->is_dir) {
|
if (entry_obj->ent.entry->is_dir&& !entry_obj->ent.entry->is_zip && !entry_obj->ent.entry->is_tar) {
|
||||||
if (!entry_obj->ent.entry->is_zip && !entry_obj->ent.entry->is_tar && entry_obj->ent.entry->filename) {
|
if (entry_obj->ent.entry->filename) {
|
||||||
efree(entry_obj->ent.entry->filename);
|
efree(entry_obj->ent.entry->filename);
|
||||||
entry_obj->ent.entry->filename = NULL;
|
entry_obj->ent.entry->filename = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2323,7 +2355,7 @@ PHP_METHOD(PharFileInfo, chmod)
|
||||||
long perms;
|
long perms;
|
||||||
PHAR_ENTRY_OBJECT();
|
PHAR_ENTRY_OBJECT();
|
||||||
|
|
||||||
if (entry_obj->ent.entry->is_dir) {
|
if (entry_obj->ent.entry->is_dir && (!entry_obj->ent.entry->is_tar && !entry_obj->ent.entry->is_zip)) {
|
||||||
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
|
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
|
||||||
"Phar entry is a directory, cannot chmod"); \
|
"Phar entry is a directory, cannot chmod"); \
|
||||||
}
|
}
|
||||||
|
@ -2728,6 +2760,9 @@ zend_function_entry php_archive_methods[] = {
|
||||||
PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
|
PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Phar, uncompressAllFiles, NULL, ZEND_ACC_PUBLIC)
|
PHP_ME(Phar, uncompressAllFiles, NULL, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC)
|
PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC)
|
||||||
|
PHP_ME(Phar, isTar, NULL, ZEND_ACC_PUBLIC)
|
||||||
|
PHP_ME(Phar, isZip, NULL, ZEND_ACC_PUBLIC)
|
||||||
|
PHP_ME(Phar, isPhar, NULL, ZEND_ACC_PUBLIC)
|
||||||
#endif
|
#endif
|
||||||
/* static member functions */
|
/* static member functions */
|
||||||
PHP_ME(Phar, apiVersion, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
|
PHP_ME(Phar, apiVersion, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
|
||||||
|
|
|
@ -125,18 +125,20 @@ int phar_is_tar(char *buf)
|
||||||
int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
|
int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
phar_archive_data *phar;
|
phar_archive_data *phar;
|
||||||
int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
|
int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, options, &phar, error TSRMLS_CC);
|
||||||
|
|
||||||
|
if (pphar) {
|
||||||
|
*pphar = phar;
|
||||||
|
}
|
||||||
if (FAILURE == ret) {
|
if (FAILURE == ret) {
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
if ((*pphar)->is_tar) {
|
if (phar->is_tar) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
phar = *pphar;
|
|
||||||
if (phar->is_brandnew) {
|
if (phar->is_brandnew) {
|
||||||
phar->is_tar = 1;
|
phar->is_tar = 1;
|
||||||
|
phar->internal_file_start = 0;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,6 +233,9 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
|
||||||
if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry.flags)) {
|
if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry.flags)) {
|
||||||
entry.tar_type = TAR_DIR;
|
entry.tar_type = TAR_DIR;
|
||||||
}
|
}
|
||||||
|
if (entry.tar_type == TAR_DIR) {
|
||||||
|
entry.is_dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
entry.link = NULL;
|
entry.link = NULL;
|
||||||
if (entry.tar_type == TAR_LINK) {
|
if (entry.tar_type == TAR_LINK) {
|
||||||
|
@ -366,7 +371,11 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||||
if (entry->fp) {
|
if (entry->fp) {
|
||||||
/* new file */
|
/* new file */
|
||||||
file = entry->fp;
|
file = entry->fp;
|
||||||
|
if (file == entry->phar->fp) {
|
||||||
|
php_stream_seek(file, entry->offset_within_phar, SEEK_SET);
|
||||||
|
} else {
|
||||||
php_stream_seek(file, 0, SEEK_SET);
|
php_stream_seek(file, 0, SEEK_SET);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
file = fp->old;
|
file = fp->old;
|
||||||
php_stream_seek(file, entry->offset_within_phar, SEEK_SET);
|
php_stream_seek(file, entry->offset_within_phar, SEEK_SET);
|
||||||
|
@ -381,10 +390,13 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
|
||||||
memset(padding, 0, 512);
|
memset(padding, 0, 512);
|
||||||
php_stream_write(fp->new, padding, ((entry->uncompressed_filesize +511)&~511) - entry->uncompressed_filesize);
|
php_stream_write(fp->new, padding, ((entry->uncompressed_filesize +511)&~511) - entry->uncompressed_filesize);
|
||||||
|
|
||||||
if (entry->fp) {
|
entry->is_modified = 0;
|
||||||
|
if (entry->fp && entry->fp_refcount == 0) {
|
||||||
|
if (entry->fp != entry->phar->fp) {
|
||||||
php_stream_close(entry->fp);
|
php_stream_close(entry->fp);
|
||||||
entry->fp = NULL;
|
entry->fp = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* note new location within tar */
|
/* note new location within tar */
|
||||||
entry->offset_within_phar = pos;
|
entry->offset_within_phar = pos;
|
||||||
|
@ -405,6 +417,7 @@ int phar_tar_flush(phar_archive_data *archive, char *user_stub, long len, char *
|
||||||
entry.is_modified = 1;
|
entry.is_modified = 1;
|
||||||
entry.is_tar = 1;
|
entry.is_tar = 1;
|
||||||
entry.tar_type = '0';
|
entry.tar_type = '0';
|
||||||
|
entry.phar = archive;
|
||||||
/* set alias */
|
/* set alias */
|
||||||
if (archive->is_explicit_alias) {
|
if (archive->is_explicit_alias) {
|
||||||
entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1);
|
entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue