Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/miniz
diff options
context:
space:
mode:
authorLukáš Hejl <hejl.lukas@gmail.com>2021-05-20 20:44:12 +0300
committerLukáš Hejl <hejl.lukas@gmail.com>2021-05-20 20:44:12 +0300
commitf50046b31bc2b8c7ef36e21778cf5e889e945d7f (patch)
tree39088754cb659fe3e1c98b34b407ba80267e4c64 /src/miniz
parent6bb2982b98644916d721cadd627ebc9fbc2e38ac (diff)
Modified streaming interface in miniz library to use ZIP64 extension only for files exciding the limits.
The modification is based on a preallocation space in the Extra field using a phony custom block in the Local file header. This space is eventually overwritten by the ZIP64 extension if the file exceeds 4GiB. Also were fixed differences from PKZip specification in the streaming interface.
Diffstat (limited to 'src/miniz')
-rw-r--r--src/miniz/miniz.c119
1 files changed, 68 insertions, 51 deletions
diff --git a/src/miniz/miniz.c b/src/miniz/miniz.c
index 08126f441..cff9aa5d3 100644
--- a/src/miniz/miniz.c
+++ b/src/miniz/miniz.c
@@ -5953,17 +5953,16 @@ static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64
static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
{
- (void)pZip;
memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
- MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, (pZip->m_pState->m_zip64) ? 0x002D : (method ? 0x0014 : 0x0000));
MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
- MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
- MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
+ MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, (pZip->m_pState->m_zip64 || comp_size > MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size);
+ MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, (pZip->m_pState->m_zip64 || uncomp_size > MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size);
MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
return MZ_TRUE;
@@ -5975,10 +5974,12 @@ static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_
mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
{
- (void)pZip;
+ mz_zip_internal_state *pState = pZip->m_pState;
+ mz_bool is_zip64_needed = uncomp_size >= MZ_UINT32_MAX || comp_size >= MZ_UINT32_MAX;
memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
- MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_MADE_BY_OFS, is_zip64_needed ? 0x002D : (method ? 0x0014 : 0x0000));
+ MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, is_zip64_needed ? 0x002D : (method ? 0x0014 : 0x0000));
MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
@@ -6675,6 +6676,15 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
return MZ_TRUE;
}
+static mz_uint32 mz_zip_writer_preallocate_extra_data(mz_uint8 *pBuf, mz_uint32 extra_data_size)
+{
+ mz_uint8 *pDst = pBuf;
+ MZ_WRITE_LE16(pDst + 0, 0x9999);
+ MZ_WRITE_LE16(pDst + 2, extra_data_size);
+ memset(pDst + 4, 0, extra_data_size);
+ return 2 * sizeof(mz_uint16) + extra_data_size;
+}
+
mz_bool mz_zip_writer_add_staged_open(mz_zip_archive* pZip, mz_zip_writer_staged_context* pContext, const char* pArchive_name, mz_uint64 max_size, const MZ_TIME_T* pFile_time, const void* pComment, mz_uint16 comment_size, mz_uint level_and_flags,
const char* user_extra_data, mz_uint user_extra_data_len, const char* user_extra_data_central, mz_uint user_extra_data_central_len)
{
@@ -6708,13 +6718,6 @@ mz_bool mz_zip_writer_add_staged_open(mz_zip_archive* pZip, mz_zip_writer_staged
pState = pZip->m_pState;
- if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX))
- {
- /* Source file is too large for non-zip64 */
- /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
- pState->m_zip64 = MZ_TRUE;
- }
-
/* We could support this, but why? */
if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
@@ -6778,55 +6781,45 @@ mz_bool mz_zip_writer_add_staged_open(mz_zip_archive* pZip, mz_zip_writer_staged
MZ_ASSERT((pContext->cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
}
+ if (!pState->m_zip64 && (pContext->local_dir_header_ofs >= MZ_UINT32_MAX)) {
+ pState->m_zip64 = MZ_TRUE;
+ /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
+ }
+
MZ_CLEAR_OBJ(local_dir_header);
if (pState->m_zip64)
{
- if (max_size >= MZ_UINT32_MAX || pContext->local_dir_header_ofs >= MZ_UINT32_MAX)
- {
- pContext->pExtra_data = pContext->extra_data;
- pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, (max_size >= MZ_UINT32_MAX) ? &pContext->uncomp_size : NULL,
- (max_size >= MZ_UINT32_MAX) ? &pContext->comp_size : NULL, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL);
- }
+ pContext->pExtra_data = pContext->extra_data;
+ pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, &pContext->uncomp_size, &pContext->comp_size,
+ (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL);
+ }
+ else if (!pState->m_zip64 && max_size > MZ_UINT32_MAX)
+ {
+ pContext->pExtra_data = pContext->extra_data;
+ pContext->extra_size = mz_zip_writer_preallocate_extra_data(pContext->extra_data, 2 * sizeof(mz_uint64));
+ }
- if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)pContext->archive_name_size, (mz_uint16)(pContext->extra_size + user_extra_data_len), 0, 0, 0, pContext->method, pContext->gen_flags, pContext->dos_time, pContext->dos_date))
- return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
+ if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)pContext->archive_name_size, (mz_uint16)(pContext->extra_size + user_extra_data_len), 0, 0, 0, pContext->method, pContext->gen_flags, pContext->dos_time, pContext->dos_date))
+ return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
- if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
- return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
+ return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
- pContext->cur_archive_file_ofs += sizeof(local_dir_header);
+ pContext->cur_archive_file_ofs += sizeof(local_dir_header);
- if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pArchive_name, pContext->archive_name_size) != pContext->archive_name_size)
- {
- return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
- }
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pArchive_name, pContext->archive_name_size) != pContext->archive_name_size)
+ {
+ return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
+ }
- pContext->cur_archive_file_ofs += pContext->archive_name_size;
+ pContext->cur_archive_file_ofs += pContext->archive_name_size;
+ if (pState->m_zip64 || max_size >= MZ_UINT32_MAX) {
if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pContext->extra_data, pContext->extra_size) != pContext->extra_size)
return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
pContext->cur_archive_file_ofs += pContext->extra_size;
}
- else
- {
- if ((pContext->comp_size > MZ_UINT32_MAX) || (pContext->cur_archive_file_ofs > MZ_UINT32_MAX))
- return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
- if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)pContext->archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, pContext->method, pContext->gen_flags, pContext->dos_time, pContext->dos_date))
- return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
-
- if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
- return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
-
- pContext->cur_archive_file_ofs += sizeof(local_dir_header);
-
- if (pZip->m_pWrite(pZip->m_pIO_opaque, pContext->cur_archive_file_ofs, pArchive_name, pContext->archive_name_size) != pContext->archive_name_size)
- {
- return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
- }
-
- pContext->cur_archive_file_ofs += pContext->archive_name_size;
- }
if (user_extra_data_len > 0)
{
@@ -6898,17 +6891,40 @@ mz_bool mz_zip_writer_add_staged_finish(mz_zip_writer_staged_context *pContext)
pContext->pZip->m_pFree(pContext->pZip->m_pAlloc_opaque, pContext->pCompressor);
pContext->pCompressor = NULL;
+ // Rewrite preallocated phony custom block in local dir header by ZIP64 extension. Also, other values are adjusted in the header.
+ if (pContext->file_ofs >= MZ_UINT32_MAX || pContext->add_state.m_comp_size >= MZ_UINT32_MAX) {
+ mz_uint64 local_dir_header_ofs = pContext->local_dir_header_ofs;
+ pContext->pExtra_data = pContext->extra_data;
+ pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, &pContext->uncomp_size, &pContext->comp_size, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL);
+
+ mz_uint8 min_version[2] = {0x2D, 0x00};
+ mz_uint8 comp_uncomp_size[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+ if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LDH_VERSION_NEEDED_OFS, min_version, sizeof(min_version)) != sizeof(min_version))
+ return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED);
+ if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_uncomp_size, sizeof(comp_uncomp_size)) != sizeof(comp_uncomp_size))
+ return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED);
+ if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, comp_uncomp_size, sizeof(comp_uncomp_size)) != sizeof(comp_uncomp_size))
+ return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED);
+ if (pContext->pZip->m_pWrite(pContext->pZip->m_pIO_opaque, local_dir_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + pContext->archive_name_size, pContext->extra_data, pContext->extra_size) != pContext->extra_size)
+ return mz_zip_set_error(pContext->pZip, MZ_ZIP_FILE_WRITE_FAILED);
+ }
+
pContext->uncomp_size = pContext->file_ofs;
pContext->comp_size = pContext->add_state.m_comp_size;
pContext->cur_archive_file_ofs = pContext->add_state.m_cur_archive_file_ofs;
+ // Clean pContext->pExtra_data, pContext->extra_data and pContext->extra_size after calling mz_zip_writer_add_staged_open
+ pContext->pExtra_data = NULL;
+ pContext->extra_size = 0;
+ memset(pContext->extra_data, 0, sizeof(mz_uint8) * MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE);
+
{
mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
MZ_WRITE_LE32(local_dir_footer + 4, pContext->uncomp_crc32);
- if (pContext->pExtra_data == NULL)
+ if (pContext->uncomp_size < MZ_UINT32_MAX && pContext->comp_size < MZ_UINT32_MAX)
{
if (pContext->comp_size > MZ_UINT32_MAX)
return mz_zip_set_error(pContext->pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
@@ -6929,10 +6945,11 @@ mz_bool mz_zip_writer_add_staged_finish(mz_zip_writer_staged_context *pContext)
pContext->cur_archive_file_ofs += local_dir_footer_size;
}
- if (pContext->pExtra_data != NULL)
+ if (pContext->file_ofs >= MZ_UINT32_MAX || pContext->add_state.m_comp_size >= MZ_UINT32_MAX)
{
+ pContext->pExtra_data = pContext->extra_data;
pContext->extra_size = mz_zip_writer_create_zip64_extra_data(pContext->extra_data, (pContext->uncomp_size >= MZ_UINT32_MAX) ? &pContext->uncomp_size : NULL,
- (pContext->uncomp_size >= MZ_UINT32_MAX) ? &pContext->comp_size : NULL, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL);
+ (pContext->comp_size >= MZ_UINT32_MAX) ? &pContext->comp_size : NULL, (pContext->local_dir_header_ofs >= MZ_UINT32_MAX) ? &pContext->local_dir_header_ofs : NULL);
}
if (!mz_zip_writer_add_to_central_dir(pContext->pZip, pContext->pArchive_name, (mz_uint16)pContext->archive_name_size, pContext->pExtra_data, (mz_uint16)pContext->extra_size, pContext->pComment, pContext->comment_size,