[System.IO.Compression] Fixed DeflateStream inflate() decompression loop.
authorJoao Matos <joao@tritao.eu>
Thu, 27 Oct 2016 18:12:31 +0000 (19:12 +0100)
committerJoao Matos <joao@tritao.eu>
Thu, 27 Oct 2016 19:44:38 +0000 (20:44 +0100)
This reworks the fix from https://github.com/mono/mono/commit/7c4d41a518aaf0370b882f9430752ebcd5544c10.

That fix introduced a regression when handling some inputs, which lead us to ignore
some left-over data from zlib's inflate output buffer.

Now we only break from the loop if inflate() returns Z_BUF_ERROR.

This makes sure all data is fully processed before returning to managed code.

Fixes one of the bugs in https://bugzilla.xamarin.com/show_bug.cgi?id=44994#c2.

mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs
support/zlib-helper.c

index 0fe01aaf102cd2c04b499ef4f1822e4da01a6955..4fef4c5f4d8f083fcd50ca8a315940ec01bc83c3 100644 (file)
@@ -410,6 +410,27 @@ namespace MonoTests.System.IO.Compression
                        using (var unZippedStream = new StreamReader (gZipStream, Encoding.UTF8)) {
                                unZipped = unZippedStream.ReadToEnd ();
                        }
+
+                       Assert.AreEqual(1877, unZipped.Length);
+               }
+
+               [Test]
+               public void Bug44994_Inflate()
+               {
+                       var base64String = @"7cWxCQAgDACwpeBjgqsgXiHU0fd9QzBLErX1EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADepcxcuU/atm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm3btm37zy8=";
+
+                       byte[] byteArray = Convert.FromBase64String(base64String);
+                       string unZipped = null;
+
+                       using (var zippedMemoryStream = new MemoryStream(byteArray))
+                       using (var gZipStream = new DeflateStream(zippedMemoryStream, CompressionMode.Decompress))
+                       using (var unzippedMemStream = new MemoryStream())
+                       using (var unZippedStream = new StreamReader(gZipStream, Encoding.UTF8))
+                       {
+                               unZipped = unZippedStream.ReadToEnd();
+                       }
+
+                       Assert.AreEqual(81942, unZipped.Length);
                }
        }
 }
index f364a66095fcaf23a35524746f18d4accf891736..5e07a2e21ce4d90071d4247820ae8cea706accd5 100644 (file)
@@ -202,13 +202,16 @@ ReadZStream (ZStream *stream, guchar *buffer, gint length)
                        zs->avail_in = n < 0 ? 0 : n;
                }
 
-               if (zs->avail_in == 0 && (zs->total_in == 0 || stream->total_in == zs->total_in))
-                       return Z_STREAM_END;
+               if (zs->avail_in == 0 && zs->total_in == 0)
+                       return 0;
 
                status = inflate (stream->stream, Z_SYNC_FLUSH);
                if (status == Z_STREAM_END) {
                        stream->eof = TRUE;
                        break;
+               } else if (status == Z_BUF_ERROR && stream->total_in == zs->total_in) {
+                       stream->eof = TRUE;
+                       break;
                } else if (status != Z_OK) {
                        return status;
                }