XE 10.2.3 ZLib库可能存在严重bug

日总是我哥 2019-04-02 03:56:48
数年没发帖了,上来特别提醒DELPHI用户注意这个问题。

在调用System.ZLib.ZDecompressStream时,某些情况可能陷入死循环,无法退出。


procedure ZDecompressStream(inStream, outStream: TStream);
const
bufferSize = 32768;
var
zstream: TZStreamRec;
zresult: Integer;
inBuffer: TBytes;
outBuffer: TBytes;
inSize: Integer;
outSize: Integer;
begin
SetLength(inBuffer, BufferSize);
SetLength(outBuffer, BufferSize);
FillChar(zstream, SizeOf(TZStreamRec), 0);

ZDecompressCheck(InflateInit(zstream));

try
inSize := inStream.Read(inBuffer, bufferSize);
while inSize > 0 do
begin
zstream.next_in := @inBuffer[0];
zstream.avail_in := inSize;

repeat
zstream.next_out := @outBuffer[0];
zstream.avail_out := bufferSize;

ZDecompressCheckWithoutBufferError(inflate(zstream, Z_NO_FLUSH));

outSize := bufferSize - zstream.avail_out;

outStream.Write(outBuffer, outSize);
until (zstream.avail_in = 0) and (zstream.avail_out > 0);

inSize := inStream.Read(inBuffer, bufferSize);
end;

repeat
zstream.next_out := @outBuffer[0];
zstream.avail_out := bufferSize;

zresult := ZDecompressCheckWithoutBufferError(inflate(zstream, Z_FINISH)); <--------------

outSize := bufferSize - zstream.avail_out;

outStream.Write(outBuffer, outSize);
until (zresult = Z_STREAM_END) and (zstream.avail_out > 0);
finally
ZDecompressCheck(inflateEnd(zstream));
end;
end;




function ZDecompressCheckWithoutBufferError(code: Integer): Integer; overload;
begin
Result := code;

if code < 0 then
if (code <> Z_BUF_ERROR) then <------------罪魁祸首
raise EZDecompressionError.Create(string(_z_errmsg[2 - code]));
end;



尚不清楚XE 10.2.3的ZLib代码为什么在code = Z_BUF_ERROR的时候,不抛出异常。

导致的后果是一直在repeat中死循环。
...全文
707 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
那只是zlib压缩后输出的二进制数据,不代表ZIP文件格式,ZIP除了压缩算法之外还有自己的文件格式(文件头),你把zip文件的文件头删掉看看7zip能不能识别?
CACACACACA 2019-05-16
  • 打赏
  • 举报
回复
COPY Code Examples 代码,TZCompressionStream生成的zip,7Z居然说是无效的文件。
ckbyh 2019-04-08
  • 打赏
  • 举报
回复
QuickReport 5.06 Pro Delphi XE8 这个控件在xe8中稳定 吗?初学者。谢谢!
BlueStorm 2019-04-04
  • 打赏
  • 举报
回复
旧版本里面不排除Z_BUF_ERROR这个警告信息才是BUG。 现在Delphi 10.3里面的Indy idCompressorZLib.pas还有这个BUG
日总是我哥 2019-04-03
  • 打赏
  • 举报
回复
引用 5 楼 BlueStorm 的回复:
Z_BUF_ERROR只是一个警告,而不是一个错误,意思是解压缩后的数据块的大小超过了缓冲区的大小了,但解压缩还能正常进行。
你的问题估计是其他原因导致的。


你这估计有点意思啊,我的文件是损坏了,但是也不能一直在里面死循环不出来吧。
  • 打赏
  • 举报
回复
没有BUG,ZDecompressCheckWithoutBufferError,就是忽略Z_BUF_ERROR
BlueStorm 2019-04-02
  • 打赏
  • 举报
回复
Z_BUF_ERROR只是一个警告,而不是一个错误,意思是解压缩后的数据块的大小超过了缓冲区的大小了,但解压缩还能正常进行。 你的问题估计是其他原因导致的。
lao_yunger 2019-04-02
  • 打赏
  • 举报
回复
if (code <> Z_BUF_ERROR) then <------------罪魁祸首 raise EZDecompressionError.Create(string(_z_errmsg[2 - code])); 上面应当是if code = Z_BUF_ERROR) then raise EZDecompressionError.Create(string(_z_errmsg[2 - code])); 逻辑上才行得通
秋天之落叶 2019-04-02
  • 打赏
  • 举报
回复
10.2.3编译的时候有警示信息吗?可能有些函数为了跨平台而修改了,没测试。
日总是我哥 2019-04-02
  • 打赏
  • 举报
回复
也欢迎你贴不同DELPHI版本的ZLib函数代码出来,看看哪些版本可能存在这个问题。
日总是我哥 2019-04-02
  • 打赏
  • 举报
回复
再看DELPHI 2010的ZLib库,完全OK


procedure ZDecompressStream(inStream, outStream: TStream);
const
bufferSize = 32768;
var
zstream: TZStreamRec;
zresult: Integer;
inBuffer: array[0..bufferSize - 1] of AnsiChar;
outBuffer: array[0..bufferSize - 1] of AnsiChar;
inSize: Integer;
outSize: Integer;
begin
FillChar(zstream, SizeOf(TZStreamRec), 0);

ZCompressCheck(InflateInit(zstream));

inSize := inStream.Read(inBuffer, bufferSize);

while inSize > 0 do
begin
zstream.next_in := inBuffer;
zstream.avail_in := inSize;

repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;

ZCompressCheck(inflate(zstream, Z_NO_FLUSH));

// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;

outStream.Write(outBuffer, outSize);
until (zstream.avail_in = 0) and (zstream.avail_out > 0);

inSize := inStream.Read(inBuffer, bufferSize);
end;

repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;

zresult := ZCompressCheck(inflate(zstream, Z_FINISH));

// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;

outStream.Write(outBuffer, outSize);
until (zresult = Z_STREAM_END) and (zstream.avail_out > 0);

ZCompressCheck(inflateEnd(zstream));
end;




function ZCompressCheck(code: Integer): Integer;
begin
result := code;

if code < 0 then
begin
raise EZCompressionError.Create(_z_errmsg[2 - code]);
end;
end;

function ZDecompressCheck(code: Integer): Integer;
begin
Result := code;

if code < 0 then
begin
raise EZDecompressionError.Create(_z_errmsg[2 - code]);
end;
end;
本课程采用了漫画+动手实操+练习讲授Python编程技能。课程简介:第6章 容器类型数据6.1 序列6.1.1 序列的索引操作6.1.2 加与乘操作6.1.3 切片操作6.1.4 成员测试6.2 列表6.2.1 创建列表6.2.2 追加元素6.2.3 插入元素6.2.4 替换元素6.2.5 删除元素6.3 元组6.3.1 创建元组6.3.2 元组拆包6.4 集合6.4.1 创建集合6.4.2 修改集合6.5 字典6.5.1 创建字典6.5.2 修改字典6.5.3 访问字典视图6.6 动动手 —— 遍历字典6.7 练一练第7章 字符串7.1 字符串的表示方式7.1.1 普通字符串7.1.2 原始字符串7.1.3 长字符串7.2 字符串与数字的相互转换7.2.1 将字符串转换为数字7.2.2 将数字转换为字符串7.3 格式化字符串7.3.1 使用占位符7.3.2 格式化控制符7.4 操作字符串7.4.1 字符串查找7.4.2 字符串替换7.4.3 字符串分割7.5 动动手 —— 统计英文文章中单词出现的频率7.6 练一练第8章 函数8.1 定义函数8.2 调用函数8.2.1 使用位置参数调用函数8.2.2 使用关键字参数调用函数8.3 参数的默认值8.4 可变参数8.4.1 基于元组的可变参数( *可变参数)8.4.2 基于字典的可变参数( **可变参数)8.5 函数中变量的作用域8.6 函数类型8.6.1 理解函数类型8.6.2 过滤函数filter()8.6.3 映射函数map()8.7 lambda()函数8.8 动动手 —— 使用更多的lambda()函数8.9 练一练第9章 类与对象9.1 面向对象9.2 定义类9.3 创建对象9.4 类的成员9.4.1 实例变量9.4.2 构造方法9.4.3 实例方法9.4.4 类变量19.5 封装9.5.1 私有变量9.5.2 私有方法9.5.3 使用属性9.6 继承性9.6.1 Python中的继承9.6.2 多继承9.6.3 重写方法9.7 多态性9.7.1 继承与多态9.7.2 鸭子类型测试与多态9.8 练一练第10章 异常处理9.8 练一练10.1 第一个异常 —— 除零异常10.2 捕获异常110.2.1 try-except语句10.2.2 多个except代码块10.2.3 多重异常捕获10.2.4 try-except语句嵌套10.3 使用finally代码块释放资源10.4 自定义异常类10.5 动动手 —— 手动引发异常10.6 练一练

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧