Ошибка в модуле idZLibCompressorBase
Для обработки gzip/deflate часто используется модуль idZLibCompressorBase. В принципе, модуль неплохо справляется со своими функциями пока не попадутся “криво” сжатые данные. В некоторых случаях может возникнуть бесконечный цикл считывания со всеми вытекающими неприятностями. Вот ошибочный код:
procedure GotoDataStart; var LFlags:byte; LExtra:word; LNullFindChar:char; begin AStream.Seek(3,soFromCurrent); AStream.Read(LFlags,1); AStream.Seek(6,soFromCurrent); // at pos 10 now if LFlags and $4 = $4 then begin // FEXTRA AStream.Read(LExtra, 2); AStream.Seek(LExtra, soFromCurrent); end; if LFlags and $8 = $8 then begin // FNAME repeat AStream.Read(LNullFindChar, 1) until LNullFindChar=#0; end; if LFlags and $10 = $10 then begin // FCOMMENT repeat AStream.Read(LNullFindChar, 1) until LNullFindChar=#0; end; if LFlags and $2 = $2 then begin // FHCRC AStream.Seek(2, soFromCurrent); // CRC16 end; end;
В циклах repeat может возникнуть проблема, если нет нулевого символа #0, поэтому необходимо проверять длину прочитанных байт и выходить из цикла, если прочитать не удалось:
procedure GotoDataStart; var LFlags:byte; LExtra:word; LNullFindChar:char; begin AStream.Seek(3,soFromCurrent); AStream.Read(LFlags,1); AStream.Seek(6,soFromCurrent); // at pos 10 now if LFlags and $4 = $4 then begin // FEXTRA AStream.Read(LExtra, 2); AStream.Seek(LExtra, soFromCurrent); end; if LFlags and $8 = $8 then begin // FNAME repeat if AStream.Read(LNullFindChar, 1) = 0 then break; until LNullFindChar=#0; end; if LFlags and $10 = $10 then begin // FCOMMENT repeat if AStream.Read(LNullFindChar, 1) = 0 then break; until LNullFindChar=#0; end; if LFlags and $2 = $2 then begin // FHCRC AStream.Seek(2, soFromCurrent); // CRC16 end; end;
Циклическое считывание данных довольно часто применяется, пример показывает возможную ошибку - необходимо проверять количество прочитанных байт!
См. также:
Настоящий iconv для Delphi это возможно!
Обрабатываем HTML
Base64 в Delphi
