From: Greg Beaver Date: Thu, 4 Oct 2007 03:33:21 +0000 (+0000) Subject: fix Bug #12124: Phar object cannot be iterated over X-Git-Tag: RELEASE_2_0_0a1~1665 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eb67969b73c0ad3e3cfef1ceaa434a55ae29a5aa;p=php fix Bug #12124: Phar object cannot be iterated over remove unused variables fix jit file open sprintf calls --- diff --git a/ext/phar/phar.c b/ext/phar/phar.c index c1086f7ee3..2d956d1850 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -331,6 +331,14 @@ static int phar_get_archive(phar_archive_data **archive, char *fname, int fname_ * retrieve information on a file contained within a phar, or null if it ain't there */ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC) /* {{{ */ +{ + return phar_get_entry_info_dir(phar, path, path_len, 0, error TSRMLS_CC); +} +/* }}} */ +/** + * retrieve information on a file or directory contained within a phar, or null if none found + */ +phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error TSRMLS_DC) /* {{{ */ { const char *pcr_error; phar_entry_info *entry; @@ -356,6 +364,41 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int pa } return entry; } + if (dir) { + /* try to find a directory */ + HashTable *manifest; + char *key; + uint keylen; + ulong unused; + + manifest = &phar->manifest; + zend_hash_internal_pointer_reset(manifest); + while (FAILURE != zend_hash_has_more_elements(manifest)) { + if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) { + break; + } + if (0 != memcmp(key, path, path_len)) { + /* entry in directory not found */ + if (SUCCESS != zend_hash_move_forward(manifest)) { + break; + } + continue; + } else { + if (key[path_len] != '/') { + if (SUCCESS != zend_hash_move_forward(manifest)) { + break; + } + continue; + } + /* found a file in this path */ + entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info)); + entry->is_dir = 1; + entry->filename = (char *) estrndup(path, path_len + 1); + entry->filename_len = path_len; + return entry; + } + } + } return NULL; } /* }}} */ @@ -1707,7 +1750,7 @@ static phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info offset = phar->internal_file_start + entry->offset_within_phar; if (-1 == php_stream_seek(fp, offset, SEEK_SET)) { spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (cannot seek to start of file \"%s\" at offset \"%d\")", - phar->fname, entry, offset); + phar->fname, entry->filename, offset); return NULL; } @@ -1724,7 +1767,7 @@ static phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info filter = NULL; } if (!filter) { - spprintf(error, 0, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry); + spprintf(error, 0, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry->filename); return NULL; } /* now we can safely use proper decompression */ @@ -1791,16 +1834,11 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat { phar_entry_data *idata; char *internal_file; - char *buffer; char *error; - char *filter_name; char *plain_map; - char tmpbuf[8]; HashTable *pharcontext; php_url *resource = NULL; php_stream *fp, *fpf; - php_stream_filter *filter/*, *consumed */; - php_uint32 offset, read, total, toread; zval **pzoption, *metadata; uint host_len; @@ -2220,7 +2258,7 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err long offset; size_t wrote; php_uint32 manifest_len, mytime, loc, new_manifest_count; - php_uint32 newcrc32, save; + php_uint32 newcrc32; php_stream *file, *oldfile, *newfile, *stubfile; php_stream_filter *filter; php_serialize_data_t metadata_hash; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index e591ea31f5..f2f2e55be8 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -159,6 +159,8 @@ typedef struct _phar_entry_info { int is_crc_checked:1; int is_modified:1; int is_deleted:1; + /* used when iterating */ + int is_dir:1; phar_archive_data *phar; smart_str metadata_str; } phar_entry_info; @@ -271,6 +273,7 @@ int phar_archive_delref(phar_archive_data *phar TSRMLS_DC); int phar_entry_delref(phar_entry_data *idata TSRMLS_DC); phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC); +phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error TSRMLS_DC); phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC); int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC); int phar_detect_phar_fname_ext(const char *filename, int check_length, char **ext_str, int *ext_len); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index d2b7e963a7..64b3a77f1c 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1083,10 +1083,10 @@ PHP_METHOD(PharFileInfo, __construct) return; } - if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len, &error TSRMLS_CC)) == NULL) { - efree(arch); + if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error TSRMLS_CC)) == NULL) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error?", ":"", error?error:""); + efree(arch); efree(entry); return; } @@ -1112,13 +1112,31 @@ PHP_METHOD(PharFileInfo, __construct) return; \ } +/* {{{ proto void PharFileInfo::__destruct() + * clean up directory-based entry objects + */ +PHP_METHOD(PharFileInfo, __destruct) +{ + PHAR_ENTRY_OBJECT(); + + if (entry_obj->ent.entry->is_dir) { + if (entry_obj->ent.entry->filename) { + efree(entry_obj->ent.entry->filename); + entry_obj->ent.entry->filename = NULL; + } + efree(entry_obj->ent.entry); + entry_obj->ent.entry = NULL; + } +} +/* }}} */ + /* {{{ proto int PharFileInfo::getCompressedSize() * Returns the compressed size */ PHP_METHOD(PharFileInfo, getCompressedSize) { PHAR_ENTRY_OBJECT(); - + RETURN_LONG(entry_obj->ent.entry->compressed_filesize); } /* }}} */ @@ -1163,6 +1181,10 @@ PHP_METHOD(PharFileInfo, getCRC32) { PHAR_ENTRY_OBJECT(); + if (entry_obj->ent.entry->is_dir) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \ + "Phar entry is a directory, does not have a CRC"); \ + } if (entry_obj->ent.entry->is_crc_checked) { RETURN_LONG(entry_obj->ent.entry->crc32); } else { @@ -1203,6 +1225,10 @@ PHP_METHOD(PharFileInfo, chmod) long perms; PHAR_ENTRY_OBJECT(); + if (entry_obj->ent.entry->is_dir) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \ + "Phar entry is a directory, cannot chmod"); \ + } if (PHAR_G(readonly)) { zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Cannot modify permissions for file \"%s\" write operations are prohibited", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname); } @@ -1268,6 +1294,10 @@ PHP_METHOD(PharFileInfo, setMetadata) zval *metadata; PHAR_ENTRY_OBJECT(); + if (entry_obj->ent.entry->is_dir) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \ + "Phar entry is a directory, cannot set metadata"); \ + } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &metadata) == FAILURE) { return; } @@ -1296,6 +1326,10 @@ PHP_METHOD(PharFileInfo, delMetadata) char *error; PHAR_ENTRY_OBJECT(); + if (entry_obj->ent.entry->is_dir) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \ + "Phar entry is a directory, cannot delete metadata"); \ + } if (entry_obj->ent.entry->metadata) { zval_ptr_dtor(&entry_obj->ent.entry->metadata); entry_obj->ent.entry->metadata = NULL; @@ -1323,6 +1357,10 @@ PHP_METHOD(PharFileInfo, setCompressedGZ) char *error; PHAR_ENTRY_OBJECT(); + if (entry_obj->ent.entry->is_dir) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \ + "Phar entry is a directory, cannot set compression"); \ + } if (entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) { RETURN_TRUE; return; @@ -1363,6 +1401,10 @@ PHP_METHOD(PharFileInfo, setCompressedBZIP2) char *error; PHAR_ENTRY_OBJECT(); + if (entry_obj->ent.entry->is_dir) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \ + "Phar entry is a directory, cannot set compression"); \ + } if (entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) { RETURN_TRUE; return; @@ -1403,6 +1445,10 @@ PHP_METHOD(PharFileInfo, setUncompressed) int fname_len; PHAR_ENTRY_OBJECT(); + if (entry_obj->ent.entry->is_dir) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \ + "Phar entry is a directory, cannot set compression"); \ + } if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) { RETURN_TRUE; return; @@ -1544,6 +1590,7 @@ ZEND_END_ARG_INFO(); zend_function_entry php_entry_methods[] = { PHP_ME(PharFileInfo, __construct, arginfo_entry___construct, 0) + PHP_ME(PharFileInfo, __destruct, NULL, 0) PHP_ME(PharFileInfo, getCompressedSize, NULL, 0) PHP_ME(PharFileInfo, isCompressed, NULL, 0) PHP_ME(PharFileInfo, isCompressedGZ, NULL, 0)