diff --git a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java index 229bd284dd..5912122cd2 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java @@ -205,12 +205,15 @@ public class JdkZlibDecoder extends ZlibDecoder { if (gzipState != GzipState.HEADER_END) { if (gzipState == GzipState.FOOTER_START) { if (!handleGzipFooter(in)) { + // Either there was not enough data or the input is finished. return; } - } else { - if (!readGZIPHeader(in)) { - return; - } + // If we consumed the footer we will start with the header again. + assert gzipState == GzipState.HEADER_START; + } + if (!readGZIPHeader(in)) { + // There was not enough data readable to read the GZIP header. + return; } // Some bytes may have been consumed, and so we must re-set the number of readable bytes. readableBytes = in.readableBytes(); diff --git a/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java b/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java index 1c8e40d805..8f6fd63d43 100644 --- a/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java +++ b/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java @@ -597,6 +597,37 @@ public class JdkZlibTest { } } + @Test + public void testDecodeWithHeaderFollowingFooter() throws Exception { + byte[] bytes = new byte[1024]; + ThreadLocalRandom.current().nextBytes(bytes); + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + GZIPOutputStream out = new GZIPOutputStream(bytesOut); + out.write(bytes); + out.close(); + + byte[] compressed = bytesOut.toByteArray(); + ByteBuf buffer = Unpooled.buffer().writeBytes(compressed).writeBytes(compressed); + EmbeddedChannel channel = new EmbeddedChannel(new JdkZlibDecoder(ZlibWrapper.GZIP, true)); + // Write it into the Channel in a way that we were able to decompress the first data completely but not the + // whole footer. + assertTrue(channel.writeInbound(buffer.readRetainedSlice(compressed.length - 1))); + assertTrue(channel.writeInbound(buffer)); + assertTrue(channel.finish()); + + ByteBuf uncompressedBuffer = Unpooled.wrappedBuffer(bytes); + ByteBuf read = channel.readInbound(); + assertEquals(uncompressedBuffer, read); + read.release(); + + read = channel.readInbound(); + assertEquals(uncompressedBuffer, read); + read.release(); + + assertNull(channel.readInbound()); + uncompressedBuffer.release(); + } + private static byte[] gzip(byte[] bytes) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream stream = new GZIPOutputStream(out);