diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index bcdd32a..6639721 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -1746,7 +1746,13 @@ rb_deflate_init_copy(VALUE self, VALUE orig) raise_zlib_error(err, 0); } z1->input = NIL_P(z2->input) ? Qnil : rb_str_dup(z2->input); - z1->buf = NIL_P(z2->buf) ? Qnil : rb_str_dup(z2->buf); + z1->buf = Qnil; + if (!NIL_P(z2->buf)) { + /* next_out was copied from orig; point it into our own buffer */ + z1->buf = rb_obj_hide(rb_str_new(RSTRING_PTR(z2->buf), RSTRING_LEN(z2->buf))); + z1->stream.next_out = (Bytef*)RSTRING_END(z1->buf); + z1->stream.avail_out = 0; + } z1->flags = z2->flags; return self; diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb index e1ecbf8..f6d29d3 100644 --- a/test/zlib/test_zlib.rb +++ b/test/zlib/test_zlib.rb @@ -39,6 +39,17 @@ def test_dup assert_equal("foobaz", Zlib::Inflate.inflate(s2)) end + def test_dup_with_pending_output + s = Random.new(0).bytes(50_000) + z1 = Zlib::Deflate.new + z1 << s + z2 = z1.dup + z1 << "bar" + z2 << "baz" + assert_equal(s + "bar", Zlib::Inflate.inflate(z1.finish)) + assert_equal(s + "baz", Zlib::Inflate.inflate(z2.finish)) + end + def test_deflate s = Zlib::Deflate.deflate("foo") assert_equal("foo", Zlib::Inflate.inflate(s))