【问题标题】:Decompressing zip file with miniz exits with status -1 (TINFL_STATUS_FAILED)使用 miniz 解压 zip 文件时退出状态为 -1 (TINFL_STATUS_FAILED)
【发布时间】:2023-10-13 21:20:01
【问题描述】:

我需要使用 miniz 库来解压我项目中的一些 zip 文件。问题是函数

tinfl_decompress

总是以TINFL_STATUS_FAILED 状态退出。

我做了一些调试,发现了 miniz.c 中有问题的代码行:

第 1452 行:

counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));

计数器设置为 1;

第 1453 行:

if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));

(((1U &lt;&lt; (8U + (r-&gt;m_zhdr0 &gt;&gt; 4))) &gt; 32768U) || ((out_buf_size_mask + 1) &lt; (size_t)(1U &lt;&lt; (8U + (r-&gt;m_zhdr0 &gt;&gt; 4))))) 评估为假;但是由于 counter 设置为 1,因此 counter 保持等于 1。

第 1454 行:

if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }

因为计数器值为 1,所以调用宏 TINFL_CR_RETURN_FOREVER。这样的宏跳转到标签common_exit

除了在我的项目内部,我还使用库中提供的示例测试了 miniz 库。具体来说,我尝试解压缩我自己的个人 zip 压缩包以及由包含在带有 example5 的 miniz 库中的 example2 生成的压缩包。

在命令提示符下发出以下命令

example5.exe d __mz_example2_test__.zip __mz_example2_test__.decompress

生成以下输出:

miniz.c example5 (demonstrates tinfl/tdefl)
Mode: d, Level: 9
Input File: "__mz_example2_test__.zip"
Output File: "__mz_example2_test__.decompress"
Input file size: 33768
tinfl_decompress() failed with status -1!

我该如何解决这个问题?我做错了什么?

【问题讨论】:

  • 问题在于zip file 是一个存档,其中存档中的每个文件都被压缩(最常见的是deflate)。但是,zip 文件本身是压缩的。要阅读 zip archive,您需要一些可以处理它的其他库。
  • @JoachimPileborg 但是miniz附带的大多数示例都显示了如何解压缩文件名作为参数传递的zip文件。
  • 如果您再次查看example 5,您会在文件#define MINIZ_NO_ARCHIVE_APIS 的前面看到,这意味着该库将没有zip 文件所需的存档功能。使用低级 compression 函数的示例,而不是归档函数(example 2)。

标签: c zip unzip zipfile inflate


【解决方案1】:

第 1452 行正在寻找 zlib 标头。 zlib 格式不是 zip 格式。您需要编写自己的 zip 格式解码器,然后在 raw inflate 模式下使用 miniz,该模式不查找 zlib 标头,而是在您通过解码 zip 标头找到的位置解码原始 deflate 数据。

或者您可以只使用libzip,它会为您完成所有这些工作。

【讨论】:

  • 如果最新版本的 libzip 不适用于您的平台/发行版,也可以推荐 libarchive。 libzip 1.0 之前的版本包含一个安全问题,该问题已在最近的版本中得到解决。
最近更新 更多