チケット #3030 が更新されました。 (by Yusuke Endoh)

担当者 Yusuke Endohにセット

遠藤です。

> 1.2.4のdeflateParams()が、すでにflushしているのに再度同じデータ
> を追加しているようです。それをちゃんとカウントしていないのは
> ext/zlibのバグだと思うのですが、zlib 1.2.4のほうもまたバグがある
> ような気がします。どっちがいいんでしょうねぇ。

zlib 1.2.5 で確かめましたが、zlib 本体にバグはないと思います。
deflateParams が flush してるのは、データではなく、byte boundary に
align させるための dummy block (展開しても長さ 0 になるブロック) の
ようです。

ext/zlib 側でわざわざ Z_SYNC_FLUSH しなければ余計なデータが出なく
なると思います。この flush は #239 を修正するために入った (r18029)
のですがこれは間違った解決方法で、今回のなかださんのパッチのように
deflatePrams 進んだ分カウンタを更新するのが正しい解決方法でした。
(まったく誰がこんな変な flush を入れたんでしょうね。)

というわけで、以下のパッチでよいと思います。


diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 435a1a6..8c3af3d 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -1371,16 +1371,20 @@ rb_deflate_params(VALUE obj, VALUE v_level, VALUE v_strategy)
     struct zstream *z = get_zstream(obj);
     int level, strategy;
     int err;
+    uInt n;
 
     level = ARG_LEVEL(v_level);
     strategy = ARG_STRATEGY(v_strategy);
 
-    zstream_run(z, (Bytef*)"", 0, Z_SYNC_FLUSH);
+    n = z->stream.avail_out;
     err = deflateParams(&z->stream, level, strategy);
+    z->buf_filled += n - z->stream.avail_out;
     while (err == Z_BUF_ERROR) {
 	rb_warning("deflateParams() returned Z_BUF_ERROR");
 	zstream_expand_buffer(z);
+	n = z->stream.avail_out;
 	err = deflateParams(&z->stream, level, strategy);
+	z->buf_filled += n - z->stream.avail_out;
     }
     if (err != Z_OK) {
 	raise_zlib_error(err, z->stream.msg);

-- 
Yusuke Endoh <mame / tsg.ne.jp>
----------------------------------------
http://redmine.ruby-lang.org/issues/show/3030

----------------------------------------
http://redmine.ruby-lang.org