From e9c62945d840c713b1e1b2ff325ce7d318586d02 Mon Sep 17 00:00:00 2001 From: GitHubProUser67 <127040195+GitHubProUser67@users.noreply.github.com> Date: Mon, 15 Sep 2025 10:33:04 +0200 Subject: [PATCH] Fixes Zlib compression issues. The current zlib implementation is "mostly" fine, but some edge cases are not simulated properly. This commit effectively puts it to parity with the C++ version. --- crypto/src/util/zlib/ZInputStream.cs | 4 +--- crypto/src/util/zlib/ZOutputStream.cs | 16 +++++++--------- crypto/src/util/zlib/ZStream.cs | 22 +++++++++++++++------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/crypto/src/util/zlib/ZInputStream.cs b/crypto/src/util/zlib/ZInputStream.cs index 67b30a3ec2..8cdd93bdab 100644 --- a/crypto/src/util/zlib/ZInputStream.cs +++ b/crypto/src/util/zlib/ZInputStream.cs @@ -51,7 +51,7 @@ private static ZStream GetDefaultZStream(bool nowrap) return z; } - private const int BufferSize = 4096; + private const int BufferSize = 512; protected ZStream z; protected int flushLevel = JZlib.Z_NO_FLUSH; @@ -186,8 +186,6 @@ public override int Read(byte[] buffer, int offset, int count) if (nomoreinput && err == JZlib.Z_BUF_ERROR) return 0; if (err != JZlib.Z_OK && err != JZlib.Z_STREAM_END) - // TODO - //throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg); throw new IOException((compress ? "de" : "in") + "flating: " + z.msg); if ((nomoreinput || err == JZlib.Z_STREAM_END) && z.avail_out == count) return 0; diff --git a/crypto/src/util/zlib/ZOutputStream.cs b/crypto/src/util/zlib/ZOutputStream.cs index 04b7bb8e59..269f22fbab 100644 --- a/crypto/src/util/zlib/ZOutputStream.cs +++ b/crypto/src/util/zlib/ZOutputStream.cs @@ -169,19 +169,18 @@ public virtual void End() public virtual void Finish() { + int err; do { z.next_out = buf; z.next_out_index = 0; z.avail_out = buf.Length; - int err = compress + err = compress ? z.deflate(JZlib.Z_FINISH) : z.inflate(JZlib.Z_FINISH); if (err != JZlib.Z_STREAM_END && err != JZlib.Z_OK) - // TODO - //throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg); throw new IOException((compress ? "de" : "in") + "flating: " + z.msg); int count = buf.Length - z.avail_out; @@ -190,7 +189,7 @@ public virtual void Finish() output.Write(buf, 0, count); } } - while (z.avail_in > 0 || z.avail_out == 0); + while ((z.avail_in > 0 || z.avail_out == 0) && err == JZlib.Z_OK); Flush(); } @@ -227,24 +226,23 @@ public override void Write(byte[] buffer, int offset, int count) z.next_in_index = offset; z.avail_in = count; + int err; do { z.next_out = buf; z.next_out_index = 0; z.avail_out = buf.Length; - int err = compress + err = compress ? z.deflate(flushLevel) : z.inflate(flushLevel); - if (err != JZlib.Z_OK) - // TODO - //throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg); + if (err != JZlib.Z_OK && err != JZlib.Z_STREAM_END) throw new IOException((compress ? "de" : "in") + "flating: " + z.msg); output.Write(buf, 0, buf.Length - z.avail_out); } - while (z.avail_in > 0 || z.avail_out == 0); + while ((z.avail_in > 0 || z.avail_out == 0) && err == JZlib.Z_OK); } public override void WriteByte(byte value) diff --git a/crypto/src/util/zlib/ZStream.cs b/crypto/src/util/zlib/ZStream.cs index 9378bf78f8..9927e91642 100644 --- a/crypto/src/util/zlib/ZStream.cs +++ b/crypto/src/util/zlib/ZStream.cs @@ -160,13 +160,21 @@ internal void flush_pending(){ if(len>avail_out) len=avail_out; if(len==0) return; - if(dstate.pending_buf.Length<=dstate.pending_out || - next_out.Length<=next_out_index || - dstate.pending_buf.Length<(dstate.pending_out+len) || - next_out.Length<(next_out_index+len)){ - // System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+ - // ", "+next_out.length+", "+next_out_index+", "+len); - // System.out.println("avail_out="+avail_out); + if (this.dstate.pending_buf.Length <= this.dstate.pending_out || this.next_out.Length <= this.next_out_index || this.dstate.pending_buf.Length < this.dstate.pending_out + len || this.next_out.Length < this.next_out_index + len) + { + Console.Out.WriteLine(string.Concat(new object[] + { + this.dstate.pending_buf.Length, + ", ", + this.dstate.pending_out, + ", ", + this.next_out.Length, + ", ", + this.next_out_index, + ", ", + len + })); + Console.Out.WriteLine("avail_out=" + this.avail_out); } System.Array.Copy(dstate.pending_buf, dstate.pending_out,