diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 7e464a2024369..c5aa292200e86 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -398,7 +398,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo if ((e = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 2, &error, 1))) { /* directory exists, or is a subdirectory of an existing file */ if (e->is_temp_dir) { - efree(e->filename); + zend_string_efree(e->filename); efree(e); } php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", directory already exists", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host)); @@ -434,14 +434,13 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo entry.is_zip = 1; } - entry.filename = estrdup(ZSTR_VAL(resource->path) + 1); + entry.filename = zend_string_init(ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, false); if (phar->is_tar) { entry.is_tar = 1; entry.tar_type = TAR_DIR; } - entry.filename_len = ZSTR_LEN(resource->path) - 1; php_url_free(resource); entry.is_dir = 1; entry.phar = phar; @@ -450,23 +449,23 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo entry.flags = PHAR_ENT_PERM_DEF_DIR; entry.old_flags = PHAR_ENT_PERM_DEF_DIR; - if (NULL == zend_hash_str_add_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info))) { - php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", entry.filename, phar->fname); + if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { + php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", ZSTR_VAL(entry.filename), phar->fname); efree(error); - efree(entry.filename); + zend_string_efree(entry.filename); return 0; } phar_flush(phar, &error); if (error) { - php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", entry.filename, phar->fname, error); - zend_hash_str_del(&phar->manifest, entry.filename, entry.filename_len); + php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(entry.filename), phar->fname, error); + zend_hash_del(&phar->manifest, entry.filename); efree(error); return 0; } - phar_add_virtual_dirs(phar, entry.filename, entry.filename_len); + phar_add_virtual_dirs(phar, ZSTR_VAL(entry.filename), ZSTR_LEN(entry.filename)); return 1; } /* }}} */ @@ -547,7 +546,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options ) { php_stream_wrapper_log_error(wrapper, options, "phar error: Directory not empty"); if (entry->is_temp_dir) { - efree(entry->filename); + zend_string_efree(entry->filename); efree(entry); } php_url_free(resource); @@ -563,7 +562,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options ) { php_stream_wrapper_log_error(wrapper, options, "phar error: Directory not empty"); if (entry->is_temp_dir) { - efree(entry->filename); + zend_string_efree(entry->filename); efree(entry); } php_url_free(resource); @@ -574,7 +573,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options if (entry->is_temp_dir) { zend_hash_str_del(&phar->virtual_dirs, ZSTR_VAL(resource->path)+1, path_len); - efree(entry->filename); + zend_string_efree(entry->filename); efree(entry); } else { entry->is_deleted = 1; @@ -582,7 +581,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options phar_flush(phar, &error); if (error) { - php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", entry->filename, phar->fname, error); + php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(entry->filename), phar->fname, error); php_url_free(resource); efree(error); return 0; diff --git a/ext/phar/phar.c b/ext/phar/phar.c index a4a9b7d2139d2..a3a2441d1e708 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -367,7 +367,7 @@ void destroy_phar_manifest_entry_int(phar_entry_info *entry) /* {{{ */ phar_metadata_tracker_free(&entry->metadata_tracker, entry->is_persistent); - pefree(entry->filename, entry->is_persistent); + zend_string_release_ex(entry->filename, entry->is_persistent); if (entry->link) { pefree(entry->link, entry->is_persistent); @@ -424,7 +424,7 @@ void phar_entry_remove(phar_entry_data *idata, char **error) /* {{{ */ if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) { php_stream_close(idata->fp); } - zend_hash_str_del(&idata->phar->manifest, idata->internal_file->filename, idata->internal_file->filename_len); + zend_hash_del(&idata->phar->manifest, idata->internal_file->filename); idata->phar->refcount--; efree(idata); } else { @@ -1134,9 +1134,10 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)") } - PHAR_GET_32(buffer, entry.filename_len); + uint32_t filename_len; + PHAR_GET_32(buffer, filename_len); - if (entry.filename_len == 0) { + if (filename_len == 0) { MAPPHAR_FAIL("zero-length filename encountered in phar \"%s\""); } @@ -1144,19 +1145,19 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname entry.manifest_pos = manifest_index; } - if (entry.filename_len > (size_t)(endbuffer - buffer - 24)) { + if (filename_len > (size_t)(endbuffer - buffer - 24)) { MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)"); } - if ((manifest_ver & PHAR_API_VER_MASK) >= PHAR_API_MIN_DIR && buffer[entry.filename_len - 1] == '/') { + if ((manifest_ver & PHAR_API_VER_MASK) >= PHAR_API_MIN_DIR && buffer[filename_len - 1] == '/') { entry.is_dir = 1; } else { entry.is_dir = 0; } - phar_add_virtual_dirs(mydata, buffer, entry.filename_len); - entry.filename = pestrndup(buffer, entry.filename_len, entry.is_persistent); - buffer += entry.filename_len; + phar_add_virtual_dirs(mydata, buffer, filename_len); + const char *filename_raw = buffer; + buffer += filename_len; PHAR_GET_32(buffer, entry.uncompressed_filesize); PHAR_GET_32(buffer, entry.timestamp); @@ -1176,13 +1177,15 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname PHAR_GET_32(buffer, entry.flags); if (entry.is_dir) { - entry.filename_len--; + filename_len--; entry.flags |= PHAR_ENT_PERM_DEF_DIR; } + entry.filename = zend_string_init(filename_raw, filename_len, entry.is_persistent); + PHAR_GET_32(buffer, len); if (len > (size_t)(endbuffer - buffer)) { - pefree(entry.filename, entry.is_persistent); + zend_string_free(entry.filename); MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)"); } /* Don't implicitly call unserialize() on potentially untrusted input unless getMetadata() is called directly. */ @@ -1199,21 +1202,21 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname case PHAR_ENT_COMPRESSED_GZ: if (!PHAR_G(has_zlib)) { phar_metadata_tracker_free(&entry.metadata_tracker, entry.is_persistent); - pefree(entry.filename, entry.is_persistent); + zend_string_free(entry.filename); MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\""); } break; case PHAR_ENT_COMPRESSED_BZ2: if (!PHAR_G(has_bz2)) { phar_metadata_tracker_free(&entry.metadata_tracker, entry.is_persistent); - pefree(entry.filename, entry.is_persistent); + zend_string_free(entry.filename); MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\""); } break; default: if (entry.uncompressed_filesize != entry.compressed_filesize) { phar_metadata_tracker_free(&entry.metadata_tracker, entry.is_persistent); - pefree(entry.filename, entry.is_persistent); + zend_string_free(entry.filename); MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)"); } break; @@ -1223,10 +1226,11 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname /* if signature matched, no need to check CRC32 for each file */ entry.is_crc_checked = (manifest_flags & PHAR_HDR_SIGNATURE ? 1 : 0); phar_set_inode(&entry); + // TODO: avoid copy if (mydata->is_persistent) { - str = zend_string_init_interned(entry.filename, entry.filename_len, 1); + str = zend_string_init_interned(ZSTR_VAL(entry.filename), ZSTR_LEN(entry.filename), 1); } else { - str = zend_string_init(entry.filename, entry.filename_len, 0); + str = zend_string_init(ZSTR_VAL(entry.filename), ZSTR_LEN(entry.filename), 0); } zend_hash_add_mem(&mydata->manifest, str, (void*)&entry, sizeof(phar_entry_info)); zend_string_release(str); @@ -2390,14 +2394,14 @@ zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char * phar_zip_data_desc desc; if (SUCCESS != phar_open_archive_fp(idata->phar)) { - spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"", idata->phar->fname, entry->filename); + spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"", idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } php_stream_seek(phar_get_entrypfp(idata->internal_file), entry->header_offset, SEEK_SET); if (sizeof(local) != php_stream_read(phar_get_entrypfp(idata->internal_file), (char *) &local, sizeof(local))) { - spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", idata->phar->fname, entry->filename); + spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } @@ -2410,7 +2414,7 @@ zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char * entry->compressed_filesize, SEEK_SET); if (sizeof(desc) != php_stream_read(phar_get_entrypfp(idata->internal_file), (char *) &desc, sizeof(desc))) { - spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")", idata->phar->fname, entry->filename); + spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")", idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } if (desc.signature[0] == 'P' && desc.signature[1] == 'K') { @@ -2421,8 +2425,8 @@ zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char * } } /* verify local header */ - if (entry->filename_len != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) { - spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local header of file \"%s\" does not match central directory)", idata->phar->fname, entry->filename); + if (ZSTR_LEN(entry->filename) != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) { + spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local header of file \"%s\" does not match central directory)", idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } @@ -2450,7 +2454,7 @@ zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char * entry->is_crc_checked = 1; return SUCCESS; } else { - spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (crc32 mismatch on file \"%s\")", idata->phar->fname, entry->filename); + spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (crc32 mismatch on file \"%s\")", idata->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } } @@ -2712,7 +2716,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } /* after excluding deleted files, calculate manifest size in bytes and number of entries */ ++new_manifest_count; - phar_add_virtual_dirs(phar, entry->filename, entry->filename_len); + phar_add_virtual_dirs(phar, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename)); if (entry->is_dir) { /* we use this to calculate API version, 1.1.1 is used for phars with directories */ @@ -2729,7 +2733,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } /* 32 bits for filename length, length of filename, manifest + metadata, and add 1 for trailing / if a directory */ - offset += 4 + entry->filename_len + sizeof(entry_buffer) + (entry->metadata_tracker.str ? ZSTR_LEN(entry->metadata_tracker.str) : 0) + (entry->is_dir ? 1 : 0); + offset += 4 + ZSTR_LEN(entry->filename) + sizeof(entry_buffer) + (entry->metadata_tracker.str ? ZSTR_LEN(entry->metadata_tracker.str) : 0) + (entry->is_dir ? 1 : 0); /* compress and rehash as necessary */ if ((oldfile && !entry->is_modified) || entry->is_dir) { @@ -2757,7 +2761,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } return; } @@ -2778,11 +2782,11 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); if (entry->flags & PHAR_ENT_COMPRESSED_GZ) { if (error) { - spprintf(error, 0, "unable to gzip compress file \"%s\" to new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to gzip compress file \"%s\" to new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } } else { if (error) { - spprintf(error, 0, "unable to bzip2 compress file \"%s\" to new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to bzip2 compress file \"%s\" to new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } } return; @@ -2815,7 +2819,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } goto cleanup; } @@ -2826,7 +2830,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } goto cleanup; } @@ -2929,13 +2933,13 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa if (entry->is_dir) { /* add 1 for trailing slash */ - phar_set_32(entry_buffer, entry->filename_len + 1); + phar_set_32(entry_buffer, ZSTR_LEN(entry->filename) + 1); } else { - phar_set_32(entry_buffer, entry->filename_len); + phar_set_32(entry_buffer, ZSTR_LEN(entry->filename)); } if (4 != php_stream_write(newfile, entry_buffer, 4) - || entry->filename_len != php_stream_write(newfile, entry->filename, entry->filename_len) + || ZSTR_LEN(entry->filename) != php_stream_write(newfile, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename)) || (entry->is_dir && 1 != php_stream_write(newfile, "/", 1))) { if (must_close_old_file) { php_stream_close(oldfile); @@ -2943,9 +2947,9 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); if (error) { if (entry->is_dir) { - spprintf(error, 0, "unable to write filename of directory \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to write filename of directory \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } else { - spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } } goto cleanup; @@ -2979,7 +2983,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } goto cleanup; @@ -3020,7 +3024,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } goto cleanup; } @@ -3032,7 +3036,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa } php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } goto cleanup; } @@ -3048,7 +3052,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); } goto cleanup; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 2f9ae7c1c84ea..736226783bef1 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -204,8 +204,7 @@ typedef struct _phar_entry_info { /* when changing compression, save old flags in case fp is NULL */ uint32_t old_flags; phar_metadata_tracker metadata_tracker; - uint32_t filename_len; - char *filename; + zend_string *filename; enum phar_fp_type fp_type; /* offset within original phar file of the file contents */ zend_long offset_abs; @@ -386,14 +385,14 @@ static inline void phar_set_inode(phar_entry_info *entry) /* {{{ */ size_t tmp_len; size_t len1, len2; - tmp_len = MIN(MAXPATHLEN, entry->filename_len + entry->phar->fname_len); + tmp_len = MIN(MAXPATHLEN, ZSTR_LEN(entry->filename) + entry->phar->fname_len); len1 = MIN(entry->phar->fname_len, tmp_len); if (entry->phar->fname) { memcpy(tmp, entry->phar->fname, len1); } - len2 = MIN(tmp_len - len1, entry->filename_len); + len2 = MIN(tmp_len - len1, ZSTR_LEN(entry->filename)); memcpy(tmp + len1, entry->filename, len2); entry->inode = (unsigned short) zend_hash_func(tmp, tmp_len); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 462e815b90a4b..c6f912cc41448 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1939,11 +1939,11 @@ static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *f if (FAILURE == phar_open_entry_fp(entry, &error, 1)) { if (error) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents: %s", entry->phar->fname, entry->filename, error); + "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents: %s", entry->phar->fname, ZSTR_VAL(entry->filename), error); efree(error); } else { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents", entry->phar->fname, entry->filename); + "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents", entry->phar->fname, ZSTR_VAL(entry->filename)); } return FAILURE; } @@ -1959,7 +1959,7 @@ static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *f if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, - "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename); + "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } @@ -2307,7 +2307,7 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert return NULL; } no_copy: - newentry.filename = estrndup(newentry.filename, newentry.filename_len); + newentry.filename = zend_string_copy(newentry.filename); phar_metadata_tracker_clone(&newentry.metadata_tracker); @@ -2325,8 +2325,8 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert newentry.phar = phar; newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */ phar_set_inode(&newentry); - zend_hash_str_add_mem(&(phar->manifest), newentry.filename, newentry.filename_len, (void*)&newentry, sizeof(phar_entry_info)); - phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len); + zend_hash_add_mem(&phar->manifest, newentry.filename, &newentry, sizeof(phar_entry_info)); + phar_add_virtual_dirs(phar, ZSTR_VAL(newentry.filename), ZSTR_LEN(newentry.filename)); } ZEND_HASH_FOREACH_END(); if ((ret = phar_rename_archive(&phar, ext))) { @@ -3504,13 +3504,12 @@ PHP_METHOD(Phar, copy) phar_metadata_tracker_clone(&newentry.metadata_tracker); - newentry.filename = estrndup(tmp_new_file, tmp_len); - newentry.filename_len = tmp_len; + newentry.filename = zend_string_copy(new_file); newentry.fp_refcount = 0; if (oldentry->fp_type != PHAR_FP) { if (FAILURE == phar_copy_entry_fp(oldentry, &newentry, &error)) { - efree(newentry.filename); + zend_string_release(newentry.filename); php_stream_close(newentry.fp); zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); efree(error); @@ -3518,7 +3517,7 @@ PHP_METHOD(Phar, copy) } } - zend_hash_str_add_mem(&oldentry->phar->manifest, ZSTR_VAL(new_file), tmp_len, &newentry, sizeof(phar_entry_info)); + zend_hash_add_mem(&oldentry->phar->manifest, newentry.filename, &newentry, sizeof(phar_entry_info)); phar_obj->archive->is_modified = 1; phar_flush(phar_obj->archive, &error); @@ -3599,7 +3598,7 @@ PHP_METHOD(Phar, offsetGet) } if (entry->is_temp_dir) { - efree(entry->filename); + zend_string_efree(entry->filename); efree(entry); } @@ -3609,7 +3608,7 @@ PHP_METHOD(Phar, offsetGet) /* Instantiate object and call constructor */ zend_result is_initialized = object_init_with_constructor(return_value, phar_obj->spl.info_class, 1, &zfname, NULL); - zval_ptr_dtor(&zfname); + zend_string_release_ex(sfname, false); if (is_initialized == FAILURE) { RETURN_THROWS(); } @@ -4158,7 +4157,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha return SUCCESS; } - if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) { + if (zend_string_starts_with_literal(entry->filename, ".phar")) { return SUCCESS; } /* strip .. from path and restrict it to be under dest directory */ @@ -4166,12 +4165,12 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha new_state.cwd[0] = DEFAULT_SLASH; new_state.cwd[1] = '\0'; new_state.cwd_length = 1; - if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND) != 0 || + if (virtual_file_ex(&new_state, ZSTR_VAL(entry->filename), NULL, CWD_EXPAND) != 0 || new_state.cwd_length <= 1) { - if (EINVAL == errno && entry->filename_len > 50) { - spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, dest); + if (EINVAL == errno && ZSTR_LEN(entry->filename) > 50) { + spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", ZSTR_VAL(entry->filename), dest); } else { - spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename); + spprintf(error, 4096, "Cannot extract \"%s\", internal error", ZSTR_VAL(entry->filename)); } efree(new_state.cwd); return FAILURE; @@ -4196,10 +4195,10 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha if (len >= MAXPATHLEN) { /* truncate for error message */ fullpath[50] = '\0'; - if (entry->filename_len > 50) { - spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath); + if (ZSTR_LEN(entry->filename) > 50) { + spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", ZSTR_VAL(entry->filename), fullpath); } else { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", ZSTR_VAL(entry->filename), fullpath); } efree(fullpath); efree(new_state.cwd); @@ -4207,14 +4206,14 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha } if (!len) { - spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename); + spprintf(error, 4096, "Cannot extract \"%s\", internal error", ZSTR_VAL(entry->filename)); efree(fullpath); efree(new_state.cwd); return FAILURE; } if (php_check_open_basedir(fullpath)) { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); efree(new_state.cwd); return FAILURE; @@ -4222,7 +4221,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha /* let see if the path already exists */ if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); efree(new_state.cwd); return FAILURE; @@ -4240,14 +4239,14 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha if (FAILURE == php_stream_stat_path(fullpath, &ssb)) { if (entry->is_dir) { if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) { - spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); efree(new_state.cwd); return FAILURE; } } else { if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) { - spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); efree(new_state.cwd); return FAILURE; @@ -4272,7 +4271,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL); if (!fp) { - spprintf(error, 4096, "Cannot extract \"%s\", could not open for writing \"%s\"", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\", could not open for writing \"%s\"", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); return FAILURE; } @@ -4280,9 +4279,9 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha if ((phar_get_fp_type(entry) == PHAR_FP && (entry->flags & PHAR_ENT_COMPRESSION_MASK)) || !phar_get_efp(entry, 0)) { if (FAILURE == phar_open_entry_fp(entry, error, 1)) { if (error) { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", ZSTR_VAL(entry->filename), fullpath, *error); } else { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer", ZSTR_VAL(entry->filename), fullpath); } efree(fullpath); php_stream_close(fp); @@ -4291,14 +4290,14 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha } if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); php_stream_close(fp); return FAILURE; } if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); php_stream_close(fp); return FAILURE; @@ -4308,7 +4307,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha mode = (mode_t) entry->flags & PHAR_ENT_PERM_MASK; if (FAILURE == VCWD_CHMOD(fullpath, mode)) { - spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", setting file permissions failed", entry->filename, fullpath); + spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", setting file permissions failed", ZSTR_VAL(entry->filename), fullpath); efree(fullpath); return FAILURE; } @@ -4331,7 +4330,7 @@ static int extract_helper(phar_archive_data *archive, zend_string *search, char } else if ('/' == ZSTR_VAL(search)[ZSTR_LEN(search) - 1]) { /* ends in "/" -- extract all entries having that prefix */ ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) { - if (0 != strncmp(ZSTR_VAL(search), entry->filename, ZSTR_LEN(search))) continue; + if (!zend_string_starts_with(entry->filename, search)) continue; if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1; extracted++; } ZEND_HASH_FOREACH_END(); @@ -4536,7 +4535,7 @@ PHP_METHOD(PharFileInfo, __destruct) if (entry_obj->entry && entry_obj->entry->is_temp_dir) { if (entry_obj->entry->filename) { - efree(entry_obj->entry->filename); + zend_string_efree(entry_obj->entry->filename); entry_obj->entry->filename = NULL; } @@ -4653,12 +4652,12 @@ PHP_METHOD(PharFileInfo, chmod) if (entry_obj->entry->is_temp_dir) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \ - "Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", entry_obj->entry->filename); \ + "Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", ZSTR_VAL(entry_obj->entry->filename)); \ RETURN_THROWS(); } if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) { - zend_throw_exception_ex(phar_ce_PharException, 0, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", entry_obj->entry->filename, entry_obj->entry->phar->fname); + zend_throw_exception_ex(phar_ce_PharException, 0, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname); RETURN_THROWS(); } @@ -4670,7 +4669,7 @@ PHP_METHOD(PharFileInfo, chmod) RETURN_THROWS(); } /* re-populate after copy-on-write */ - entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len); + entry_obj->entry = zend_hash_find_ptr(&phar->manifest, entry_obj->entry->filename); } /* clear permissions */ entry_obj->entry->flags &= ~PHAR_ENT_PERM_MASK; @@ -4765,7 +4764,7 @@ PHP_METHOD(PharFileInfo, setMetadata) RETURN_THROWS(); } /* re-populate after copy-on-write */ - entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len); + entry_obj->entry = zend_hash_find_ptr(&phar->manifest, entry_obj->entry->filename); ZEND_ASSERT(!entry_obj->entry->is_persistent); /* Should no longer be persistent */ } @@ -4815,7 +4814,7 @@ PHP_METHOD(PharFileInfo, delMetadata) RETURN_THROWS(); } /* re-populate after copy-on-write */ - entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len); + entry_obj->entry = zend_hash_find_ptr(&phar->manifest, entry_obj->entry->filename); } /* multiple values may reference the metadata */ phar_metadata_tracker_free(&entry_obj->entry->metadata_tracker, entry_obj->entry->is_persistent); @@ -4854,7 +4853,7 @@ PHP_METHOD(PharFileInfo, getContent) if (entry_obj->entry->is_dir) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, - "phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", entry_obj->entry->filename, entry_obj->entry->phar->fname); + "phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname); RETURN_THROWS(); } @@ -4866,14 +4865,14 @@ PHP_METHOD(PharFileInfo, getContent) if (SUCCESS != phar_open_entry_fp(link, &error, 0)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, - "phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error); + "phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); RETURN_THROWS(); } if (!(fp = phar_get_efp(link, 0))) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, - "phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", entry_obj->entry->filename, entry_obj->entry->phar->fname); + "phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname); RETURN_THROWS(); } @@ -4931,7 +4930,7 @@ PHP_METHOD(PharFileInfo, compress) RETURN_THROWS(); } /* re-populate after copy-on-write */ - entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len); + entry_obj->entry = zend_hash_find_ptr(&phar->manifest, entry_obj->entry->filename); } switch (method) { case PHAR_ENT_COMPRESSED_GZ: @@ -4949,7 +4948,7 @@ PHP_METHOD(PharFileInfo, compress) /* decompress this file indirectly */ if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, - "phar error: Cannot decompress bzip2-compressed file \"%s\" in phar \"%s\" in order to compress with gzip: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error); + "phar error: Cannot decompress bzip2-compressed file \"%s\" in phar \"%s\" in order to compress with gzip: %s", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); RETURN_THROWS(); } @@ -4980,7 +4979,7 @@ PHP_METHOD(PharFileInfo, compress) /* decompress this file indirectly */ if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, - "phar error: Cannot decompress gzip-compressed file \"%s\" in phar \"%s\" in order to compress with bzip2: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error); + "phar error: Cannot decompress gzip-compressed file \"%s\" in phar \"%s\" in order to compress with bzip2: %s", ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); RETURN_THROWS(); } @@ -5068,7 +5067,7 @@ PHP_METHOD(PharFileInfo, decompress) RETURN_THROWS(); } /* re-populate after copy-on-write */ - entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len); + entry_obj->entry = zend_hash_find_ptr(&phar->manifest, entry_obj->entry->filename); } switch (entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK) { case PHAR_ENT_COMPRESSED_GZ: @@ -5085,7 +5084,7 @@ PHP_METHOD(PharFileInfo, decompress) /* decompress this file indirectly */ if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) { zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, - "Phar error: Cannot decompress %s-compressed file \"%s\" in phar \"%s\": %s", compression_type, entry_obj->entry->filename, entry_obj->entry->phar->fname, error); + "Phar error: Cannot decompress %s-compressed file \"%s\" in phar \"%s\": %s", compression_type, ZSTR_VAL(entry_obj->entry->filename), entry_obj->entry->phar->fname, error); efree(error); RETURN_THROWS(); } diff --git a/ext/phar/stream.c b/ext/phar/stream.c index b7de235c82bfb..0c4b12fd73d53 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -229,7 +229,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } } if (opened_path) { - *opened_path = strpprintf(MAXPATHLEN, "phar://%s/%s", idata->phar->fname, idata->internal_file->filename); + *opened_path = zend_strpprintf_unchecked(MAXPATHLEN, "phar://%s/%S", idata->phar->fname, idata->internal_file->filename); } return fpf; } else { @@ -267,8 +267,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info)); entry->is_temp_dir = 1; - entry->filename = estrndup("", 0); - entry->filename_len = 0; + entry->filename = ZSTR_EMPTY_ALLOC(); entry->phar = phar; entry->offset = entry->offset_abs = 0; entry->compressed_filesize = entry->uncompressed_filesize = phar->halt_offset; @@ -306,13 +305,11 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } php_url_free(resource); #ifdef MBO_0 - fprintf(stderr, "Pharname: %s\n", idata->phar->filename); + fprintf(stderr, "Pharname: %s\n", idata->phar->fname); fprintf(stderr, "Filename: %s\n", internal_file); - fprintf(stderr, "Entry: %s\n", idata->internal_file->filename); + fprintf(stderr, "Entry: %s\n", ZSTR_VAL(idata->internal_file->filename)); fprintf(stderr, "Size: %u\n", idata->internal_file->uncompressed_filesize); fprintf(stderr, "Compressed: %u\n", idata->internal_file->flags); - fprintf(stderr, "Offset: %u\n", idata->internal_file->offset_within_phar); - fprintf(stderr, "Cached: %s\n", idata->internal_file->filedata ? "yes" : "no"); #endif /* check length, crc32 */ @@ -325,10 +322,10 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } if (!PHAR_G(cwd_init) && (options & STREAM_OPEN_FOR_INCLUDE)) { - char *entry = idata->internal_file->filename, *cwd; + char *entry = ZSTR_VAL(idata->internal_file->filename), *cwd; PHAR_G(cwd_init) = 1; - if ((idata->phar->is_tar || idata->phar->is_zip) && idata->internal_file->filename_len == sizeof(".phar/stub.php")-1 && !strncmp(idata->internal_file->filename, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { + if ((idata->phar->is_tar || idata->phar->is_zip) && zend_string_equals_literal(idata->internal_file->filename, ".phar/stub.php")) { /* we're executing the stub, which doesn't count as a file */ PHAR_G(cwd_init) = 0; } else if ((cwd = strrchr(entry, '/'))) { @@ -341,7 +338,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } } if (opened_path) { - *opened_path = strpprintf(MAXPATHLEN, "phar://%s/%s", idata->phar->fname, idata->internal_file->filename); + *opened_path = zend_strpprintf_unchecked(MAXPATHLEN, "phar://%s/%S", idata->phar->fname, idata->internal_file->filename); } efree(internal_file); phar_stub: @@ -448,7 +445,7 @@ static ssize_t phar_stream_write(php_stream *stream, const char *buf, size_t cou php_stream_seek(data->fp, data->position, SEEK_SET); if (count != php_stream_write(data->fp, buf, count)) { - php_stream_wrapper_log_error(stream->wrapper, stream->flags, "phar error: Could not write %d characters to \"%s\" in phar \"%s\"", (int) count, data->internal_file->filename, data->phar->fname); + php_stream_wrapper_log_error(stream->wrapper, stream->flags, "phar error: Could not write %d characters to \"%s\" in phar \"%s\"", (int) count, ZSTR_VAL(data->internal_file->filename), data->phar->fname); return -1; } data->position = php_stream_tell(data->fp); @@ -853,18 +850,17 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from * if it already exists, we overwrite the destination like what copy('phar://...', 'phar://...') does. */ entry = zend_hash_str_update_mem(&(phar->manifest), ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1, (void **)&new, sizeof(phar_entry_info)); - entry->filename = estrndup(ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1); + entry->filename = zend_string_init(ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1, false); if (FAILURE == phar_copy_entry_fp(source, entry, &error)) { php_url_free(resource_from); php_url_free(resource_to); php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error); efree(error); - zend_hash_str_del(&(phar->manifest), entry->filename, strlen(entry->filename)); + zend_hash_del(&phar->manifest, entry->filename); return 0; } is_modified = 1; entry->is_modified = 1; - entry->filename_len = strlen(entry->filename); is_dir = entry->is_dir; } else { is_dir = zend_hash_str_exists(&(phar->virtual_dirs), ZSTR_VAL(resource_from->path)+1, ZSTR_LEN(resource_from->path)-1); @@ -901,10 +897,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from is_modified = 1; entry->is_modified = 1; - efree(entry->filename); - // TODO: avoid reallocation (make entry->filename zend_string*) - entry->filename = estrndup(ZSTR_VAL(new_str_key), ZSTR_LEN(new_str_key)); - entry->filename_len = ZSTR_LEN(new_str_key); + zend_string_release(entry->filename); + entry->filename = zend_string_copy(new_str_key); zend_string_release_ex(str_key, 0); b->h = zend_string_hash_val(new_str_key); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 46f59a6042304..31a820125642f 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -177,7 +177,7 @@ static zend_result phar_tar_process_metadata(phar_entry_info *entry, php_stream phar_parse_metadata_lazy(metadata, &entry->metadata_tracker, entry->uncompressed_filesize, entry->is_persistent); - if (entry->filename_len == sizeof(".phar/.metadata.bin")-1 && !memcmp(entry->filename, ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1)) { + if (zend_string_equals_literal(entry->filename, ".phar/.metadata.bin")) { if (phar_metadata_tracker_has_data(&entry->phar->metadata_tracker, entry->phar->is_persistent)) { efree(metadata); return FAILURE; @@ -185,7 +185,7 @@ static zend_result phar_tar_process_metadata(phar_entry_info *entry, php_stream entry->phar->metadata_tracker = entry->metadata_tracker; entry->metadata_tracker.str = NULL; ZVAL_UNDEF(&entry->metadata_tracker.val); - } else if (entry->filename_len >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && NULL != (mentry = zend_hash_str_find_ptr(&(entry->phar->manifest), entry->filename + sizeof(".phar/.metadata/") - 1, entry->filename_len - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1)))) { + } else if (ZSTR_LEN(entry->filename) >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && NULL != (mentry = zend_hash_str_find_ptr(&entry->phar->manifest, ZSTR_VAL(entry->filename) + sizeof(".phar/.metadata/") - 1, ZSTR_LEN(entry->filename) - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1)))) { if (phar_metadata_tracker_has_data(&mentry->metadata_tracker, mentry->is_persistent)) { efree(metadata); return FAILURE; @@ -363,10 +363,9 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch if (!last_was_longlink && hdr->typeflag == 'L') { last_was_longlink = 1; /* support the ././@LongLink system for storing long filenames */ - entry.filename_len = entry.uncompressed_filesize; /* Check for overflow - bug 61065 */ - if (entry.filename_len == UINT_MAX || entry.filename_len == 0) { + if (entry.uncompressed_filesize == UINT_MAX || entry.uncompressed_filesize == 0) { if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (invalid entry size)", fname); } @@ -374,11 +373,12 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch phar_destroy_phar_data(myphar); return FAILURE; } - entry.filename = pemalloc(entry.filename_len+1, myphar->is_persistent); + entry.filename = zend_string_alloc(entry.uncompressed_filesize, myphar->is_persistent); + ZSTR_VAL(entry.filename)[entry.uncompressed_filesize] = '\0'; - read = php_stream_read(fp, entry.filename, entry.filename_len); - if (read != entry.filename_len) { - efree(entry.filename); + read = php_stream_read(fp, ZSTR_VAL(entry.filename), entry.uncompressed_filesize); + if (read != entry.uncompressed_filesize) { + zend_string_free(entry.filename); if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } @@ -386,7 +386,6 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch phar_destroy_phar_data(myphar); return FAILURE; } - entry.filename[entry.filename_len] = '\0'; /* skip blank stuff */ size = ((size+511)&~511) - size; @@ -394,7 +393,7 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch /* this is not good enough - seek succeeds even on truncated tars */ php_stream_seek(fp, size, SEEK_CUR); if ((uint32_t)php_stream_tell(fp) > totalsize) { - efree(entry.filename); + zend_string_free(entry.filename); if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } @@ -406,7 +405,7 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch read = php_stream_read(fp, buf, sizeof(buf)); if (read != sizeof(buf)) { - efree(entry.filename); + zend_string_free(entry.filename); if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname); } @@ -433,40 +432,39 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch } } - entry.filename_len = i+j; + uint32_t filename_len = i + j; - if (name[entry.filename_len - 1] == '/') { + if (name[filename_len - 1] == '/') { /* some tar programs store directories with trailing slash */ - entry.filename_len--; + filename_len--; } - entry.filename = pestrndup(name, entry.filename_len, myphar->is_persistent); - } else if (!last_was_longlink) { - int i; + entry.filename = zend_string_init(name, filename_len, myphar->is_persistent); + } else if (!last_was_longlink) { /* calculate strlen, which can be no longer than 100 */ - for (i = 0; i < 100; i++) { - if (hdr->name[i] == '\0') { + uint32_t filename_len; + for (filename_len = 0; filename_len < 100; filename_len++) { + if (hdr->name[filename_len] == '\0') { break; } } - entry.filename_len = i; - entry.filename = pestrndup(hdr->name, i, myphar->is_persistent); - if (i > 0 && entry.filename[entry.filename_len - 1] == '/') { + if (filename_len > 0 && hdr->name[filename_len - 1] == '/') { /* some tar programs store directories with trailing slash */ - entry.filename[entry.filename_len - 1] = '\0'; - entry.filename_len--; + filename_len--; } + + entry.filename = zend_string_init(hdr->name, filename_len, myphar->is_persistent); } last_was_longlink = 0; - phar_add_virtual_dirs(myphar, entry.filename, entry.filename_len); + phar_add_virtual_dirs(myphar, ZSTR_VAL(entry.filename), ZSTR_LEN(entry.filename)); if (sum1 != sum2) { if (error) { - spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.filename); + spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, ZSTR_VAL(entry.filename)); } - pefree(entry.filename, myphar->is_persistent); + zend_string_release_ex(entry.filename, myphar->is_persistent); php_stream_close(fp); phar_destroy_phar_data(myphar); return FAILURE; @@ -499,7 +497,7 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%.*s\"", fname, (int)linkname_len, hdr->linkname); } - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, myphar->is_persistent); php_stream_close(fp); phar_destroy_phar_data(myphar); return FAILURE; @@ -510,17 +508,17 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch } phar_set_inode(&entry); - newentry = zend_hash_str_update_mem(&myphar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info)); + newentry = zend_hash_update_mem(&myphar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); ZEND_ASSERT(newentry != NULL); if (entry.is_persistent) { ++entry.manifest_pos; } - if (entry.filename_len >= sizeof(".phar/.metadata")-1 && !memcmp(entry.filename, ".phar/.metadata", sizeof(".phar/.metadata")-1)) { + if (zend_string_starts_with_literal(entry.filename, ".phar/.metadata")) { if (FAILURE == phar_tar_process_metadata(newentry, fp)) { if (error) { - spprintf(error, 4096, "phar error: tar-based phar \"%s\" has invalid metadata in magic file \"%s\"", fname, entry.filename); + spprintf(error, 4096, "phar error: tar-based phar \"%s\" has invalid metadata in magic file \"%s\"", fname, ZSTR_VAL(entry.filename)); } php_stream_close(fp); phar_destroy_phar_data(myphar); @@ -528,7 +526,7 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch } } - if (!actual_alias && entry.filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry.filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) { + if (!actual_alias && zend_string_equals_literal(entry.filename, ".phar/alias.txt")) { /* found explicit alias */ if (size > 511) { if (error) { @@ -731,45 +729,45 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* } } - phar_add_virtual_dirs(entry->phar, entry->filename, entry->filename_len); + phar_add_virtual_dirs(entry->phar, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename)); memset((char *) &header, 0, sizeof(header)); - if (entry->filename_len > 100) { + if (ZSTR_LEN(entry->filename) > 100) { char *boundary; - if (entry->filename_len > 256) { + if (ZSTR_LEN(entry->filename) > 256) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } - boundary = entry->filename + entry->filename_len - 101; + boundary = ZSTR_VAL(entry->filename) + ZSTR_LEN(entry->filename) - 101; while (*boundary && *boundary != '/') { ++boundary; } - if (!*boundary || ((boundary - entry->filename) > 155)) { + if (!*boundary || ((boundary - ZSTR_VAL(entry->filename)) > 155)) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } - memcpy(header.prefix, entry->filename, boundary - entry->filename); - memcpy(header.name, boundary + 1, entry->filename_len - (boundary + 1 - entry->filename)); + memcpy(header.prefix, ZSTR_VAL(entry->filename), boundary - ZSTR_VAL(entry->filename)); + memcpy(header.name, boundary + 1, ZSTR_LEN(entry->filename) - (boundary + 1 - ZSTR_VAL(entry->filename))); } else { - memcpy(header.name, entry->filename, entry->filename_len); + memcpy(header.name, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename)); } phar_tar_octal(header.mode, entry->flags & PHAR_ENT_PERM_MASK, sizeof(header.mode)-1); if (FAILURE == phar_tar_octal(header.size, entry->uncompressed_filesize, sizeof(header.size)-1)) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too large for tar file format", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, filename \"%s\" is too large for tar file format", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } if (FAILURE == phar_tar_octal(header.mtime, entry->timestamp, sizeof(header.mtime)-1)) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, file modification time of file \"%s\" is too large for tar file format", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, file modification time of file \"%s\" is too large for tar file format", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } @@ -793,7 +791,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* if (FAILURE == phar_tar_octal(header.checksum, entry->crc32, sizeof(header.checksum)-1)) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, checksum of file \"%s\" is too large for tar file format", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, checksum of file \"%s\" is too large for tar file format", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } @@ -803,7 +801,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* if (sizeof(header) != php_stream_write(fp->new, (char *) &header, sizeof(header))) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, header for file \"%s\" could not be written", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, header for file \"%s\" could not be written", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } @@ -818,14 +816,14 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written, seek failed", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written, seek failed", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp->new, entry->uncompressed_filesize, NULL)) { if (fp->error) { - spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written", entry->phar->fname, entry->filename); + spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written", entry->phar->fname, ZSTR_VAL(entry->filename)); } return ZEND_HASH_APPLY_STOP; } @@ -894,8 +892,8 @@ static int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry return -1; } if (serialized_str && ZSTR_LEN(serialized_str) != php_stream_write(entry->fp, ZSTR_VAL(serialized_str), ZSTR_LEN(serialized_str))) { - spprintf(error, 0, "phar tar error: unable to write metadata to magic metadata file \"%s\"", entry->filename); - zend_hash_str_del(&(entry->phar->manifest), entry->filename, entry->filename_len); + spprintf(error, 0, "phar tar error: unable to write metadata to magic metadata file \"%s\"", ZSTR_VAL(entry->filename)); + zend_hash_del(&entry->phar->manifest, entry->filename); return ZEND_HASH_APPLY_STOP; } @@ -905,17 +903,16 @@ static int phar_tar_setmetadata(const phar_metadata_tracker *tracker, phar_entry static int phar_tar_setupmetadata(zval *zv, void *argument) /* {{{ */ { - int lookfor_len; struct _phar_pass_tar_info *i = (struct _phar_pass_tar_info *)argument; - char *lookfor, **error = i->error; + char **error = i->error; phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv), *metadata, newentry = {0}; - if (entry->filename_len >= sizeof(".phar/.metadata") && !memcmp(entry->filename, ".phar/.metadata", sizeof(".phar/.metadata")-1)) { - if (entry->filename_len == sizeof(".phar/.metadata.bin")-1 && !memcmp(entry->filename, ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1)) { + if (zend_string_starts_with_literal(entry->filename, ".phar/.metadata")) { + if (zend_string_equals_literal(entry->filename, ".phar/.metadata.bin")) { return phar_tar_setmetadata(&entry->phar->metadata_tracker, entry, error); } /* search for the file this metadata entry references */ - if (entry->filename_len >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && !zend_hash_str_exists(&(entry->phar->manifest), entry->filename + sizeof(".phar/.metadata/") - 1, entry->filename_len - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1))) { + if (ZSTR_LEN(entry->filename) >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && !zend_hash_str_exists(&entry->phar->manifest, ZSTR_VAL(entry->filename) + sizeof(".phar/.metadata/") - 1, ZSTR_LEN(entry->filename) - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1))) { /* this is orphaned metadata, erase it */ return ZEND_HASH_APPLY_REMOVE; } @@ -928,30 +925,29 @@ static int phar_tar_setupmetadata(zval *zv, void *argument) /* {{{ */ } /* now we are dealing with regular files, so look for metadata */ - lookfor_len = spprintf(&lookfor, 0, ".phar/.metadata/%s/.metadata.bin", entry->filename); + zend_string *lookfor = zend_strpprintf_unchecked(0, ".phar/.metadata/%S/.metadata.bin", entry->filename); if (!phar_metadata_tracker_has_data(&entry->metadata_tracker, entry->is_persistent)) { - zend_hash_str_del(&(entry->phar->manifest), lookfor, lookfor_len); - efree(lookfor); + zend_hash_del(&entry->phar->manifest, lookfor); + zend_string_efree(lookfor); return ZEND_HASH_APPLY_KEEP; } - if (NULL != (metadata = zend_hash_str_find_ptr(&(entry->phar->manifest), lookfor, lookfor_len))) { + if (NULL != (metadata = zend_hash_find_ptr(&entry->phar->manifest, lookfor))) { int ret; ret = phar_tar_setmetadata(&entry->metadata_tracker, metadata, error); - efree(lookfor); + zend_string_efree(lookfor); return ret; } newentry.filename = lookfor; - newentry.filename_len = lookfor_len; newentry.phar = entry->phar; newentry.tar_type = TAR_FILE; newentry.is_tar = 1; - if (NULL == (metadata = zend_hash_str_add_mem(&(entry->phar->manifest), lookfor, lookfor_len, (void *)&newentry, sizeof(phar_entry_info)))) { - efree(lookfor); - spprintf(error, 0, "phar tar error: unable to add magic metadata file to manifest for file \"%s\"", entry->filename); + if (NULL == (metadata = zend_hash_add_mem(&entry->phar->manifest, lookfor, &newentry, sizeof(phar_entry_info)))) { + zend_string_efree(lookfor); + spprintf(error, 0, "phar tar error: unable to add magic metadata file to manifest for file \"%s\"", ZSTR_VAL(entry->filename)); return ZEND_HASH_APPLY_STOP; } @@ -995,11 +991,8 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def /* set alias */ if (!phar->is_temporary_alias && phar->alias_len) { - entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1); - entry.filename_len = sizeof(".phar/alias.txt")-1; entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { - efree(entry.filename); spprintf(error, 0, "phar error: unable to create temporary file"); return; } @@ -1008,13 +1001,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def spprintf(error, 0, "unable to set alias in tar-based phar \"%s\"", phar->fname); } php_stream_close(entry.fp); - efree(entry.filename); return; } entry.uncompressed_filesize = phar->alias_len; - zend_hash_str_update_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info)); + entry.filename = ZSTR_INIT_LITERAL(".phar/alias.txt", false); + zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); /* At this point the entry is saved into the manifest. The manifest destroy routine will care about any resources to be freed. */ } else { @@ -1054,9 +1047,8 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def return; } - entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1); - entry.filename_len = sizeof(".phar/stub.php")-1; - zend_hash_str_update_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info)); + entry.filename = ZSTR_INIT_LITERAL(".phar/stub.php", false); + zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); } else { /* Either this is a brand new phar (add the stub), or the default stub is required (overwrite the stub) */ entry.fp = php_stream_fopen_tmpfile(); @@ -1073,14 +1065,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } entry.uncompressed_filesize = entry.compressed_filesize = sizeof(newstub) - 1; - entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1); - entry.filename_len = sizeof(".phar/stub.php")-1; + entry.filename = ZSTR_INIT_LITERAL(".phar/stub.php", false); if (!is_default_stub) { - if (!zend_hash_str_exists(&phar->manifest, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { - if (NULL == zend_hash_str_add_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info))) { + if (!zend_hash_exists(&phar->manifest, entry.filename)) { + if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { php_stream_close(entry.fp); - efree(entry.filename); + zend_string_efree(entry.filename); if (error) { spprintf(error, 0, "unable to create stub in tar-based phar \"%s\"", phar->fname); } @@ -1088,10 +1079,10 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } } else { php_stream_close(entry.fp); - efree(entry.filename); + zend_string_efree(entry.filename); } } else { - zend_hash_str_update_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info)); + zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); } } nostub: @@ -1133,13 +1124,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } else { phar_entry_info newentry = {0}; - newentry.filename = estrndup(".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1); - newentry.filename_len = sizeof(".phar/.metadata.bin")-1; + newentry.filename = ZSTR_INIT_LITERAL(".phar/.metadata.bin", false); newentry.phar = phar; newentry.tar_type = TAR_FILE; newentry.is_tar = 1; - if (NULL == (mentry = zend_hash_str_add_mem(&(phar->manifest), ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1, (void *)&newentry, sizeof(phar_entry_info)))) { + if (NULL == (mentry = zend_hash_add_mem(&phar->manifest, newentry.filename, &newentry, sizeof(phar_entry_info)))) { + zend_string_efree(newentry.filename); spprintf(error, 0, "phar tar error: unable to add magic metadata file to manifest for phar archive \"%s\"", phar->fname); if (must_close_old_file) { php_stream_close(oldfile); @@ -1148,7 +1139,7 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } if (ZEND_HASH_APPLY_KEEP != phar_tar_setmetadata(&phar->metadata_tracker, mentry, error)) { - zend_hash_str_del(&(phar->manifest), ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1); + zend_hash_del(&phar->manifest, newentry.filename); if (must_close_old_file) { php_stream_close(oldfile); } @@ -1188,8 +1179,6 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def return; } - entry.filename = ".phar/signature.bin"; - entry.filename_len = sizeof(".phar/signature.bin")-1; entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { spprintf(error, 0, "phar error: unable to create temporary file"); @@ -1222,10 +1211,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def return; } + ALLOCA_FLAG(use_heap); + ZSTR_ALLOCA_INIT(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1, use_heap); efree(signature); entry.uncompressed_filesize = entry.compressed_filesize = signature_length + 8; /* throw out return value and write the signature */ - entry.filename_len = phar_tar_writeheaders_int(&entry, (void *)&pass); + phar_tar_writeheaders_int(&entry, &pass); + ZSTR_ALLOCA_FREE(entry.filename, use_heap); if (error && *error) { if (must_close_old_file) { diff --git a/ext/phar/util.c b/ext/phar/util.c index f03f66c1d9dd3..06394813574b7 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -49,10 +49,13 @@ static char *phar_get_link_location(phar_entry_info *entry) /* {{{ */ if (entry->link[0] == '/') { return estrdup(entry->link + 1); } - p = strrchr(entry->filename, '/'); + p = strrchr(ZSTR_VAL(entry->filename), '/'); if (p) { - *p = '\0'; - spprintf(&ret, 0, "%s/%s", entry->filename, entry->link); + /* Important: don't modify the original `p` data because it is a shared string. */ + zend_string *new_name = zend_string_init(ZSTR_VAL(entry->filename), p - ZSTR_VAL(entry->filename), false); + spprintf(&ret, 0, "%s/%s", ZSTR_VAL(new_name), entry->link); + zend_string_release(entry->filename); + entry->filename = new_name; return ret; } return entry->link; @@ -205,11 +208,7 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil is_phar = (filename_len > 7 && !memcmp(filename, "phar://", 7)); entry.phar = phar; - entry.filename = estrndup(path, path_len); -#ifdef PHP_WIN32 - phar_unixify_path_separators(entry.filename, path_len); -#endif - entry.filename_len = path_len; + if (is_phar) { entry.tmp = estrndup(filename, filename_len); } else { @@ -223,7 +222,6 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil /* only check openbasedir for files, not for phar streams */ if (!is_phar && php_check_open_basedir(filename)) { efree(entry.tmp); - efree(entry.filename); return FAILURE; } @@ -233,16 +231,20 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil if (SUCCESS != php_stream_stat_path(filename, &ssb)) { efree(entry.tmp); - efree(entry.filename); return FAILURE; } + entry.filename = zend_string_init(path, path_len, false); +#ifdef PHP_WIN32 + phar_unixify_path_separators(ZSTR_VAL(entry.filename), path_len); +#endif + if (ssb.sb.st_mode & S_IFDIR) { entry.is_dir = 1; - if (NULL == zend_hash_str_add_ptr(&phar->mounted_dirs, entry.filename, path_len, entry.filename)) { + if (NULL == zend_hash_add_ptr(&phar->mounted_dirs, entry.filename, entry.filename)) { /* directory already mounted */ efree(entry.tmp); - efree(entry.filename); + zend_string_efree(entry.filename); return FAILURE; } } else { @@ -252,12 +254,12 @@ zend_result phar_mount_entry(phar_archive_data *phar, char *filename, size_t fil entry.flags = ssb.sb.st_mode; - if (NULL != zend_hash_str_add_mem(&phar->manifest, entry.filename, path_len, (void*)&entry, sizeof(phar_entry_info))) { + if (NULL != zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { return SUCCESS; } efree(entry.tmp); - efree(entry.filename); + zend_string_release_ex(entry.filename, false); return FAILURE; } /* }}} */ @@ -443,7 +445,7 @@ static zend_result phar_separate_entry_fp(phar_entry_info *entry, char **error) if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) { if (error) { - spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname); + spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", ZSTR_VAL(entry->filename), entry->phar->fname); } return FAILURE; } @@ -673,7 +675,6 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch /* create an entry, this is a new file */ memset(&etemp, 0, sizeof(phar_entry_info)); - etemp.filename_len = path_len; etemp.fp_type = PHAR_MOD; etemp.fp = php_stream_fopen_tmpfile(); @@ -694,8 +695,7 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_FILE; } if (is_dir && path_len) { - etemp.filename_len--; /* strip trailing / */ - path_len--; + path_len--; /* strip trailing / */ } phar_add_virtual_dirs(phar, path, path_len); @@ -703,7 +703,7 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch etemp.timestamp = time(0); etemp.is_crc_checked = 1; etemp.phar = phar; - etemp.filename = estrndup(path, path_len); + etemp.filename = zend_string_init(path, path_len, false); etemp.is_zip = phar->is_zip; if (phar->is_tar) { @@ -711,20 +711,13 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, size_t fname_len, ch etemp.tar_type = etemp.is_dir ? TAR_DIR : TAR_FILE; } - if (NULL == (entry = zend_hash_str_add_mem(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info)))) { + if (NULL == (entry = zend_hash_add_mem(&phar->manifest, etemp.filename, &etemp, sizeof(phar_entry_info)))) { php_stream_close(etemp.fp); if (error) { - spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", etemp.filename, phar->fname); + spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", ZSTR_VAL(etemp.filename), phar->fname); } efree(ret); - efree(etemp.filename); - return NULL; - } - - if (!entry) { - php_stream_close(etemp.fp); - efree(etemp.filename); - efree(ret); + zend_string_efree(etemp.filename); return NULL; } @@ -803,7 +796,7 @@ zend_result phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, c php_stream_close(dest->fp); dest->fp_type = PHAR_FP; if (error) { - spprintf(error, 4096, "phar error: unable to copy contents of file \"%s\" to \"%s\" in phar archive \"%s\"", source->filename, dest->filename, source->phar->fname); + spprintf(error, 4096, "phar error: unable to copy contents of file \"%s\" to \"%s\" in phar archive \"%s\"", ZSTR_VAL(source->filename), ZSTR_VAL(dest->filename), source->phar->fname); } return FAILURE; } @@ -891,7 +884,7 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ if (!phar_get_entrypufp(entry)) { phar_set_entrypufp(entry, php_stream_fopen_tmpfile()); if (!phar_get_entrypufp(entry)) { - spprintf(error, 4096, "phar error: Cannot open temporary file for decompressing phar archive \"%s\" file \"%s\"", phar->fname, entry->filename); + spprintf(error, 4096, "phar error: Cannot open temporary file for decompressing phar archive \"%s\" file \"%s\"", phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } } @@ -913,7 +906,7 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ } if (!filter) { - spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry->filename); + spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), ZSTR_VAL(entry->filename)); return FAILURE; } @@ -926,7 +919,7 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ if (entry->uncompressed_filesize) { if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_entrypfp(entry), ufp, entry->compressed_filesize, NULL)) { - spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename); + spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, ZSTR_VAL(entry->filename)); php_stream_filter_remove(filter, 1); return FAILURE; } @@ -937,7 +930,7 @@ zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_ php_stream_filter_remove(filter, 1); if (php_stream_tell(ufp) - loc != (zend_off_t) entry->uncompressed_filesize) { - spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename); + spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } @@ -967,7 +960,7 @@ phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, return NULL; } if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1)) { - spprintf(error, 4096, "phar error: cannot seek to start of file \"%s\" in phar \"%s\"", entry->filename, phar->fname); + spprintf(error, 4096, "phar error: cannot seek to start of file \"%s\" in phar \"%s\"", ZSTR_VAL(entry->filename), phar->fname); return NULL; } return entry; @@ -1251,6 +1244,7 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, size_t * allow_dir is 0 for none, 1 for both empty directories in the phar and temp directories, and 2 for only * valid pre-existing empty directory entries */ +// TODO: convert this to use zend_string too phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, size_t path_len, char dir, char **error, int security) /* {{{ */ { const char *pcr_error; @@ -1326,8 +1320,7 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, si entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info)); /* this next line tells PharFileInfo->__destruct() to efree the filename */ entry->is_temp_dir = entry->is_dir = 1; - entry->filename = (char *) estrndup(path, path_len + 1); - entry->filename_len = path_len; + entry->filename = zend_string_init(path, path_len, false); entry->phar = phar; return entry; } @@ -2012,6 +2005,7 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char } /* }}} */ +// TODO: convert this to zend_string too void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len) /* {{{ */ { const char *s; @@ -2051,7 +2045,7 @@ static int phar_update_cached_entry(zval *data, void *argument) /* {{{ */ entry->tmp = estrdup(entry->tmp); } - entry->filename = estrndup(entry->filename, entry->filename_len); + zend_string_addref(entry->filename); entry->is_persistent = 0; /* Replace metadata with non-persistent clones of the metadata. */ diff --git a/ext/phar/zip.c b/ext/phar/zip.c index ad0e53a80c4b2..ae06d873e8e07 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -427,26 +427,27 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia PHAR_ZIP_FAIL("Cannot process zips created from stdin (zero-length filename)"); } - entry.filename_len = PHAR_GET_16(zipentry.filename_len); - entry.filename = (char *) pemalloc(entry.filename_len + 1, entry.is_persistent); + uint32_t filename_len = PHAR_GET_16(zipentry.filename_len); + entry.filename = zend_string_alloc(filename_len, entry.is_persistent); - if (entry.filename_len != php_stream_read(fp, entry.filename, entry.filename_len)) { - pefree(entry.filename, entry.is_persistent); + if (filename_len != php_stream_read(fp, ZSTR_VAL(entry.filename), filename_len)) { + zend_string_free(entry.filename); PHAR_ZIP_FAIL("unable to read in filename from central directory, truncated"); } - entry.filename[entry.filename_len] = '\0'; - - if (entry.filename[entry.filename_len - 1] == '/') { + if (ZSTR_VAL(entry.filename)[filename_len - 1] == '/') { entry.is_dir = 1; - if(entry.filename_len > 1) { - entry.filename_len--; + if(filename_len > 1) { + filename_len--; + ZSTR_LEN(entry.filename)--; } entry.flags |= PHAR_ENT_PERM_DEF_DIR; } else { entry.is_dir = 0; } + ZSTR_VAL(entry.filename)[filename_len] = '\0'; + phar_zip_file_header local; /* Warning: only filled in when the entry is not a directory! */ if (!entry.is_dir) { /* A file has a central directory entry, and a local file header. Both of these contain the filename @@ -458,7 +459,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia php_stream_seek(fp, entry.header_offset, SEEK_SET); if (sizeof(local) != php_stream_read(fp, (char *) &local, sizeof(local))) { - pefree(entry.filename, entry.is_persistent); + zend_string_free(entry.filename); PHAR_ZIP_FAIL("phar error: internal corruption (cannot read local file header)"); } php_stream_seek(fp, current_central_dir_pos, SEEK_SET); @@ -467,29 +468,29 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia * Note: normally I'd check the crc32, and file sizes too here, but that breaks tests zip/bug48791.phpt & zip/odt.phpt, * suggesting that something may be wrong with those files or the assumption doesn't hold. Anyway, the other checks * _are_ performed for the alias file as was done in the past too. */ - if (entry.filename_len != PHAR_GET_16(local.filename_len)) { - pefree(entry.filename, entry.is_persistent); + if (ZSTR_LEN(entry.filename) != PHAR_GET_16(local.filename_len)) { + zend_string_free(entry.filename); PHAR_ZIP_FAIL("phar error: internal corruption (local file header does not match central directory)"); } entry.offset = entry.offset_abs = entry.header_offset + sizeof(phar_zip_file_header) - + entry.filename_len + + ZSTR_LEN(entry.filename) + PHAR_GET_16(local.extra_len); } else { entry.offset = entry.offset_abs = entry.header_offset + sizeof(phar_zip_file_header) - + entry.filename_len + + ZSTR_LEN(entry.filename) + PHAR_GET_16(zipentry.extra_len); } - if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) { + if (zend_string_equals_literal(entry.filename, ".phar/signature.bin")) { size_t read; php_stream *sigfile; char *sig; size_t sig_len; - pefree(entry.filename, entry.is_persistent); + zend_string_free(entry.filename); if (entry.uncompressed_filesize > 0x10000) { PHAR_ZIP_FAIL("signatures larger than 64 KiB are not supported"); @@ -543,12 +544,12 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia continue; } - phar_add_virtual_dirs(mydata, entry.filename, entry.filename_len); + phar_add_virtual_dirs(mydata, ZSTR_VAL(entry.filename), ZSTR_LEN(entry.filename)); if (PHAR_GET_16(zipentry.extra_len)) { zend_off_t loc = php_stream_tell(fp); if (FAILURE == phar_zip_process_extra(fp, &entry, PHAR_GET_16(zipentry.extra_len))) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("Unable to process extra field header for file in central directory"); } php_stream_seek(fp, loc + PHAR_GET_16(zipentry.extra_len), SEEK_SET); @@ -561,62 +562,62 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia case PHAR_ZIP_COMP_DEFLATE : entry.flags |= PHAR_ENT_COMPRESSED_GZ; if (!PHAR_G(has_zlib)) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("zlib extension is required"); } break; case PHAR_ZIP_COMP_BZIP2 : entry.flags |= PHAR_ENT_COMPRESSED_BZ2; if (!PHAR_G(has_bz2)) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("bzip2 extension is required"); } break; case 1 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (Shrunk) used in this zip"); case 2 : case 3 : case 4 : case 5 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (Reduce) used in this zip"); case 6 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (Implode) used in this zip"); case 7 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (Tokenize) used in this zip"); case 9 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (Deflate64) used in this zip"); case 10 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (PKWare Implode/old IBM TERSE) used in this zip"); case 14 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (LZMA) used in this zip"); case 18 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (IBM TERSE) used in this zip"); case 19 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (IBM LZ77) used in this zip"); case 97 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (WavPack) used in this zip"); case 98 : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (PPMd) used in this zip"); default : - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unsupported compression method (unknown) used in this zip"); } /* get file metadata */ if (PHAR_GET_16(zipentry.comment_len)) { if (PHAR_GET_16(zipentry.comment_len) != php_stream_read(fp, buf, PHAR_GET_16(zipentry.comment_len))) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in file comment, truncated"); } @@ -626,7 +627,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia ZVAL_UNDEF(&entry.metadata_tracker.val); } - if (!actual_alias && entry.filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry.filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) { + if (!actual_alias && zend_string_equals_literal(entry.filename, ".phar/alias.txt")) { php_stream_filter *filter; /* archive alias found */ @@ -634,7 +635,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia /* verify local header */ ZEND_ASSERT(!entry.is_dir); if (entry.crc32 != PHAR_GET_32(local.crc32) || entry.uncompressed_filesize != PHAR_GET_32(local.uncompsize) || entry.compressed_filesize != PHAR_GET_32(local.compsize)) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("phar error: internal corruption of zip-based phar (local header of alias does not match central directory)"); } @@ -653,7 +654,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia filter = php_stream_filter_create("zlib.inflate", NULL, php_stream_is_persistent(fp)); if (!filter) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to decompress alias, zlib filter creation failed"); } @@ -674,7 +675,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } if (!entry.uncompressed_filesize || !actual_alias) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); } @@ -685,7 +686,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp)); if (!filter) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, bzip2 filter creation failed"); } @@ -706,7 +707,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } if (!entry.uncompressed_filesize || !actual_alias) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); } @@ -728,7 +729,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } if (!entry.uncompressed_filesize || !actual_alias) { - pefree(entry.filename, entry.is_persistent); + zend_string_release_ex(entry.filename, entry.is_persistent); PHAR_ZIP_FAIL("unable to read in alias, truncated"); } } @@ -738,7 +739,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia } phar_set_inode(&entry); - zend_hash_str_add_mem(&mydata->manifest, entry.filename, entry.filename_len, (void *)&entry, sizeof(phar_entry_info)); + zend_hash_add_mem(&mydata->manifest, entry.filename, &entry, sizeof(phar_entry_info)); } if (zend_hash_str_exists(&(mydata->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) { @@ -892,7 +893,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ } } - phar_add_virtual_dirs(entry->phar, entry->filename, entry->filename_len); + phar_add_virtual_dirs(entry->phar, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename)); memset(&local, 0, sizeof(local)); memset(¢ral, 0, sizeof(central)); memset(&perms, 0, sizeof(perms)); @@ -925,8 +926,8 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ phar_zip_u2d_time(entry->timestamp, local.timestamp, local.datestamp); memcpy(central.timestamp, local.timestamp, sizeof(local.timestamp)); memcpy(central.datestamp, local.datestamp, sizeof(local.datestamp)); - PHAR_SET_16(central.filename_len, entry->filename_len + (entry->is_dir ? 1 : 0)); - PHAR_SET_16(local.filename_len, entry->filename_len + (entry->is_dir ? 1 : 0)); + PHAR_SET_16(central.filename_len, ZSTR_LEN(entry->filename) + (entry->is_dir ? 1 : 0)); + PHAR_SET_16(local.filename_len, ZSTR_LEN(entry->filename) + (entry->is_dir ? 1 : 0)); // set language encoding flag (all filenames have to be UTF-8 anyway) general_purpose_flags = PHAR_GET_16(central.flags); PHAR_SET_16(central.flags, general_purpose_flags | (1 << 11)); @@ -950,7 +951,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ } if (FAILURE == phar_open_entry_fp(entry, p->error, 0)) { - spprintf(p->error, 0, "unable to open file contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to open file contents of file \"%s\" in zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -961,7 +962,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ } if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { - spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -986,9 +987,9 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ if (!filter) { if (entry->flags & PHAR_ENT_COMPRESSED_GZ) { - spprintf(p->error, 0, "unable to gzip compress file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to gzip compress file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); } else { - spprintf(p->error, 0, "unable to bzip2 compress file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to bzip2 compress file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); } return ZEND_HASH_APPLY_STOP; } @@ -999,21 +1000,21 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ entry->cfp = php_stream_fopen_tmpfile(); if (!entry->cfp) { - spprintf(p->error, 0, "unable to create temporary file for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to create temporary file for file \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } php_stream_flush(efp); if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) { - spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to seek to start of file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } php_stream_filter_append((&entry->cfp->writefilters), filter); if (SUCCESS != php_stream_copy_to_stream_ex(efp, entry->cfp, entry->uncompressed_filesize, NULL)) { - spprintf(p->error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -1036,7 +1037,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ PHAR_SET_32(local.compsize, entry->compressed_filesize); if (p->old) { if (-1 == php_stream_seek(p->old, entry->offset_abs, SEEK_SET)) { - spprintf(p->error, 0, "unable to seek to start of file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to seek to start of file \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } } @@ -1052,64 +1053,64 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ } entry->header_offset = php_stream_tell(p->filefp); - offset = entry->header_offset + sizeof(local) + entry->filename_len + (entry->is_dir ? 1 : 0) + sizeof(perms); + offset = entry->header_offset + sizeof(local) + ZSTR_LEN(entry->filename) + (entry->is_dir ? 1 : 0) + sizeof(perms); if (sizeof(local) != php_stream_write(p->filefp, (char *)&local, sizeof(local))) { - spprintf(p->error, 0, "unable to write local file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write local file header of file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } if (sizeof(central) != php_stream_write(p->centralfp, (char *)¢ral, sizeof(central))) { - spprintf(p->error, 0, "unable to write central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write central directory entry for file \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } if (entry->is_dir) { - if (entry->filename_len != php_stream_write(p->filefp, entry->filename, entry->filename_len)) { - spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + if (ZSTR_LEN(entry->filename) != php_stream_write(p->filefp, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename))) { + spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } if (1 != php_stream_write(p->filefp, "/", 1)) { - spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } - if (entry->filename_len != php_stream_write(p->centralfp, entry->filename, entry->filename_len)) { - spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + if (ZSTR_LEN(entry->filename) != php_stream_write(p->centralfp, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename))) { + spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } if (1 != php_stream_write(p->centralfp, "/", 1)) { - spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } } else { - if (entry->filename_len != php_stream_write(p->filefp, entry->filename, entry->filename_len)) { - spprintf(p->error, 0, "unable to write filename to local directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + if (ZSTR_LEN(entry->filename) != php_stream_write(p->filefp, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename))) { + spprintf(p->error, 0, "unable to write filename to local directory entry for file \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } - if (entry->filename_len != php_stream_write(p->centralfp, entry->filename, entry->filename_len)) { - spprintf(p->error, 0, "unable to write filename to central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + if (ZSTR_LEN(entry->filename) != php_stream_write(p->centralfp, ZSTR_VAL(entry->filename), ZSTR_LEN(entry->filename))) { + spprintf(p->error, 0, "unable to write filename to central directory entry for file \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } } if (sizeof(perms) != php_stream_write(p->filefp, (char *)&perms, sizeof(perms))) { - spprintf(p->error, 0, "unable to write local extra permissions file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write local extra permissions file header of file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } if (sizeof(perms) != php_stream_write(p->centralfp, (char *)&perms, sizeof(perms))) { - spprintf(p->error, 0, "unable to write central extra permissions file header of file \"%s\" to zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write central extra permissions file header of file \"%s\" to zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } if (!not_really_modified && entry->is_modified) { if (entry->cfp) { if (SUCCESS != php_stream_copy_to_stream_ex(entry->cfp, p->filefp, entry->compressed_filesize, NULL)) { - spprintf(p->error, 0, "unable to write compressed contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write compressed contents of file \"%s\" in zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } @@ -1123,7 +1124,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ phar_seek_efp(entry, 0, SEEK_SET, 0, 0); if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), p->filefp, entry->uncompressed_filesize, NULL)) { - spprintf(p->error, 0, "unable to write contents of file \"%s\" in zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write contents of file \"%s\" in zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } } @@ -1149,7 +1150,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ } if (!entry->is_dir && entry->compressed_filesize && SUCCESS != php_stream_copy_to_stream_ex(p->old, p->filefp, entry->compressed_filesize, NULL)) { - spprintf(p->error, 0, "unable to copy contents of file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to copy contents of file \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } } @@ -1160,7 +1161,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ if (entry->metadata_tracker.str) { if (ZSTR_LEN(entry->metadata_tracker.str) != php_stream_write(p->centralfp, ZSTR_VAL(entry->metadata_tracker.str), ZSTR_LEN(entry->metadata_tracker.str))) { - spprintf(p->error, 0, "unable to write metadata as file comment for file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname); + spprintf(p->error, 0, "unable to write metadata as file comment for file \"%s\" while creating zip-based phar \"%s\"", ZSTR_VAL(entry->filename), entry->phar->fname); return ZEND_HASH_APPLY_STOP; } } @@ -1212,8 +1213,6 @@ static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pas return FAILURE; } - entry.filename = ".phar/signature.bin"; - entry.filename_len = sizeof(".phar/signature.bin")-1; entry.fp = php_stream_fopen_tmpfile(); entry.fp_type = PHAR_MOD; entry.is_modified = 1; @@ -1235,11 +1234,14 @@ static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pas return FAILURE; } + ALLOCA_FLAG(use_heap); + ZSTR_ALLOCA_INIT(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1, use_heap); efree(signature); entry.uncompressed_filesize = entry.compressed_filesize = signature_length + 8; entry.phar = phar; /* throw out return value and write the signature */ phar_zip_changed_apply_int(&entry, (void *)pass); + ZSTR_ALLOCA_FREE(entry.filename, use_heap); php_stream_close(newfile); if (pass->error && *(pass->error)) { @@ -1298,10 +1300,9 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } entry.uncompressed_filesize = entry.compressed_filesize = phar->alias_len; - entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1); - entry.filename_len = sizeof(".phar/alias.txt")-1; + entry.filename = ZSTR_INIT_LITERAL(".phar/alias.txt", false); - zend_hash_str_update_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info)); + zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); } else { zend_hash_str_del(&phar->manifest, ".phar/alias.txt", sizeof(".phar/alias.txt")-1); } @@ -1346,10 +1347,9 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def return; } - entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1); - entry.filename_len = sizeof(".phar/stub.php")-1; + entry.filename = ZSTR_INIT_LITERAL(".phar/stub.php", false); - zend_hash_str_update_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info)); + zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); } else { /* Either this is a brand new phar (add the stub), or the default stub is required (overwrite the stub) */ entry.fp = php_stream_fopen_tmpfile(); @@ -1366,14 +1366,13 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } entry.uncompressed_filesize = entry.compressed_filesize = sizeof(newstub) - 1; - entry.filename = estrndup(".phar/stub.php", sizeof(".phar/stub.php")-1); - entry.filename_len = sizeof(".phar/stub.php")-1; + entry.filename = ZSTR_INIT_LITERAL(".phar/stub.php", false); if (!is_default_stub) { - if (!zend_hash_str_exists(&phar->manifest, ".phar/stub.php", sizeof(".phar/stub.php")-1)) { - if (NULL == zend_hash_str_add_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info))) { + if (!zend_hash_exists(&phar->manifest, entry.filename)) { + if (NULL == zend_hash_add_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info))) { php_stream_close(entry.fp); - efree(entry.filename); + zend_string_efree(entry.filename); if (error) { spprintf(error, 0, "unable to create stub in zip-based phar \"%s\"", phar->fname); } @@ -1381,10 +1380,10 @@ void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } } else { php_stream_close(entry.fp); - efree(entry.filename); + zend_string_efree(entry.filename); } } else { - zend_hash_str_update_mem(&phar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info)); + zend_hash_update_mem(&phar->manifest, entry.filename, &entry, sizeof(phar_entry_info)); } } nostub: