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中死循环。
...全文
706 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;

5,388

社区成员

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

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