致命的なバグの修正

HLIT と HDIST のデコードに関するバグ修正

Inflate において、リテラルと長さ符号(HLIT)と距離符号(HDIST)の展開において不具合があったため、Inflate に失敗あるいは正しくないデータになってしまうことがありました。 これはどういうことかと言うと、HLIT と HDIST は連続して格納されていますが、その中で同じ符号が連続する場合は繰り返しを行う処理があります。 0.2.0 までの実装では、HLIT と HDIST をそれぞれ別の配列として扱っていたため、 HLIT と HDIST をまたぐような繰り返し符号が出現していた際、誤ったデータが展開されてしまっていました。

0.3.0 では HLIT と HDIST の展開を連続する配列として展開し、その後のハフマン符号テーブルを構築する際に HLIT と HDIST を分離して行うようにしています。

仕様でいうと RFC1951 の 3.2.7 にある以下の部分を誤って実装していたということです。

The code length repeat codes can cross from HLIT + 257 to the
HDIST + 1 code lengths.  In other words, all code lengths form
a single sequence of HLIT + HDIST + 258 values.

不正な Deflate データによる無限ループの修正

0.2.0 までは細工された Deflate データを伸長しようとすると、無限ループに陥る場合がありました。 ハフマン符号を使ってリテラル・長さ符号と距離符号を取得する際、ハフマン符号のコード長が不正になっており、無限に読み込もうとして無限ループに陥ってました。

0.3.0 ではコード長をチェックして明らかに不正な場合、例外を投げるように修正しました。

その他のバグ修正

PKZIP 作成時、余計な領域が後ろに残っているバグの修正

0.2.0 までは PKZIP の作成を行うと、後ろに余計な領域が残っており、厳密なアーカイバで展開しようとすると「データのペイロード後にデータが存在します」という警告が出ていました。 これは "End of central directory record" のサイズ計算が誤っていて、余分にバッファを確保してしまうせいです。

https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT の 4.3.16 にある通り、22 が正しいサイズです。

このバグと修正方法についてはzlib.js 0.2.0のzip.js/zip.min.jsのバグの修正[ZIPファイルの破損]によって報告されていました。 @TakeshiOkamoto さん、ありがとうございました。

ビルド・テスト環境の変更

Ant によるビルドと BusterJS によるテストから、 Grunt によるビルドと Karma + mocha + power-assert によるテストに変更しました。 Grunt にする作業自体はだいぶ前に行っていたのですが、すでに時代遅れになっている気もするのでさらに変更するかもしれません…。