JZlibと
“Java7で看取られたバグ(享年12)”
         について


                  @ymnk



Java SE 7 Launch Event in Sendai (2011/09/04)
自己紹介
• 山中淳彦(@ymnk)
• 株式会社ジェイクラフト (JCraft,Inc.)
• FLOSSを幾つか開発 ・公開
  JSch、JZlib、JOrbis など
• Eclipse.org、Liftwebでコミッタ
• Scala勉強会@東北 (通算110回程、休止中)
• 仕事でJava、最近 Scala
• http://facebook.com/aymnk
自己紹介
• ymnkの書いたソフトがBoeing 787に搭載
 JCraft's X Server Part of Boeing 787 Avionics Systems
 http://www.jcraft.com/news/06.18.2009pr.html
いきなり結論
内容
• Bug ID: 4206909
• JZlib
• Zlib
• Deflateアルゴリズム
• SYNC_FLUSHの使用例
• java.util.zip まつわる話題
• まとめ
Bug ID: 4206909
Bug ID: 4206909
• http://bugs.sun.com/view_bug.do?bug_id=4206909
• Synopsis: want java.util.zip to work for
  interactive use (Z_SYNC_FLUSH)
• Submit Date: 28-JAN-1999
• Reported Against: 1.2, 1.3, 1.1.7, 1.1.8
• Release Fixed: 7(b77)
• State: 10-Fix Delivered, request for
  enhancement
Bug ID: 4206909
• Description:

 “Today it is not possible to reuse
 java.util.zip for compression because the
 Java VM calls deflate() in the libz with
 Z_NO_FLUSH (and Z_FINISH for EOF)
 only.”
Bug ID: 4206909
• Description:

 “ This means that in most cases the
 deflate() does not emit enough data for
 the decompressor to reassemble the
 complete data packet because it waits for
 more input.”
Bug ID: 4206909
• java.util.zip パッケージ
   – Deflater
   一般的な ZLIB 圧縮ライブラリを使用して汎用の圧縮
   アルゴリズムをサポート
  – Inflater
   一般的な ZLIB 圧縮ライブラリを使用して汎用の圧縮
   解除をサポート
  – InflaterInputStream
  – DeflaterOutputStream
Bug ID: 4206909
Java6まで(j.u.z.Deflater#deflate+NO_FLUSH)

•“Hello”を圧縮して伸張しても”Hello”が得られるとは限らない
•双方向でやり取りする場合、デッドロックになる可能性がある

  “Hello”
               compressor
                             “lo”は処理待ち


                              “Hel”
              decompressor
Bug ID: 4206909
Java7(j.u.z.Deflater#deflate+SYNC_FLUSH)

•“Hello”をSYNC_FLUSHで圧縮して伸張すると必ず
”Hello”が得られる

 “Hello”
               compressor


                              “Hello”
              decompressor
で、いままではどうしてた?
JZlib
JZlib
•   zlib(1.1.3)のpure Java実装
•   修正BSDライセンスで公開
•   2000年12月より ymnk が開発
•   最近、Inflater/Deflaterでgzip
    format(RFC1952)を操作できるようにhack中
JZlib
• 開発の動機
  SSHのパケット圧縮[RFC4253]実現のため

 “The 'zlib' compression is described in
 [RFC1950] and in [RFC1951].The
 compression context is initialized after each
 key exchange, and is passed from one packet
 to the next, with only a partial flush being
 performed at the end of each packet. “
JZlib
• JZlibを使っているソフトウェア
 – JSch
 – Apache MINA
 – Netty
 – Zimbra
 – as3zlib
 – Zlib.cs
 – IronPython.Zlib
 – Nokia Data Gathering 等
zlib
zlib
• Wikipediaから
 “zlibは、データの圧縮および伸張を行うためのフリーの
 ライブラリである。可逆圧縮アルゴリズムの Deflate
 (RFC 1951)を実装している。ヘッダーやフッターなどの
 データ形式はRFC 1950 (ZLIB Compressed Data
 Format Specification)として仕様化されている。”
zlib
• 作者: Jean-Loup Gailly, Mark Adler
• ライセンス: zlib license
• GIF特許問題を受けて開発開始
• 当初は、性能・効率よりは、特許に触れないよう
  に開発
 ITmedia: LZWに震え上がった10年前の人たち
 Glamenv-Septzen.net: 技術/歴史/zip,gzip,zlib,bzip2
Deflate アルゴリズム
Deflate アルゴリズム
• Wikipediaから
 “LZ77とハフマン符号化を組み合わせた可逆データ圧
 縮アルゴリズム。”
                                       特許あり

   LZ77         LZ78                        LZW

                            GIF
                            Compress コマンド



    LZSS          Deflate       PNG
                                zlib、gzip

                 特許なし(と広く信じられている)
SYNC_FLUSHの使用例
SYNC_FLUSHの使用例
scala> val defl_infl = {
    import java.util.zip._
    val (defl, infl, buf) = (new Deflater, new Inflater, new Array[Byte](100))
    def f(in: String): String = synchronized {
     in.getBytes match {
      case result =>
         defl.setInput(result)
         defl.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH) match{
         case l =>  l は buf に書き出された圧縮データのサイズ
                   //
         infl.setInput(buf, 0, l)
         val len = infl.inflate(result, 0, result.length)
          new String(result, 0, len)
      }}} // ちゃんと実装するには、中間バッファ(buf)の溢れに注意
    f_    // また、伸張後のバッファ溢れにも注意すべき
}
SYNC_FLUSHの使用例
scala> println(new java.io.File(".").list.forall{ l => defl_infl(l)==l })
true
java.util.zip まつわる話題
java.util.zip にまつわる話題
• JDK は native な zlib を独自に抱えてる
 2002年ごろ double free 問題で大騒ぎに
 zlib 1.1.3の問題
 S ymantec: Zlib compression library double free bug could allow arbitrary code Zlib

• Inflaterがgzip format(RFC1952)を処理できない
  zlib 1.2からの機能 (Java6以降は zlib 1.2.3を使用)
  最近、JRubyのZip::Inflaterの実装で話題に
  JRubyでj.u.zipに代わって、JZlib を使うかも?
• zlibのinflaterSyncをInflaterから使えない
まとめ
JZlib and an aged fixed bug in java7

JZlib and an aged fixed bug in java7