From 37c776687812762d155c2b6e7157a549bd98cd68 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Sat, 19 Jul 2014 15:55:15 +0400 Subject: [PATCH] Fixes for compression codecs Motivation: Fixed founded mistakes in compression codecs. Modifications: - Changed return type of ZlibUtil.inflaterException() from CompressionException to DecompressionException - Updated @throws in javadoc of JZlibDecoder to throw DecompressionException instead of CompressionException - Fixed JdkZlibDecoder to throw DecompressionException instead of CompressionException - Removed unnecessary empty lines in JdkZlibEncoder and JZlibEncoder - Removed public modifier from Snappy class - Added MAX_UNCOMPRESSED_DATA_SIZE constant in SnappyFramedDecoder - Used in.readableBytes() instead of (in.writerIndex() - in.readerIndex()) in SnappyFramedDecoder - Added private modifier for enum ChunkType in SnappyFramedDecoder - Fixed potential bug (sum overflow) in Bzip2HuffmanAllocator.first(). For more info, see http://googleresearch.blogspot.ru/2006/06/extra-extra-read-all-about-it-nearly.html Result: Fixed sum overflow in Bzip2HuffmanAllocator, improved exceptions in ZlibDecoder implementations, hid Snappy class --- .../codec/compression/Bzip2HuffmanAllocator.java | 2 +- .../netty/handler/codec/compression/JZlibDecoder.java | 6 +++--- .../netty/handler/codec/compression/JZlibEncoder.java | 1 - .../handler/codec/compression/JdkZlibDecoder.java | 11 +++++------ .../handler/codec/compression/JdkZlibEncoder.java | 1 - .../io/netty/handler/codec/compression/Snappy.java | 2 +- .../codec/compression/SnappyFramedDecoder.java | 10 ++++++---- .../io/netty/handler/codec/compression/ZlibUtil.java | 4 ++-- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2HuffmanAllocator.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2HuffmanAllocator.java index 70a3fd53e7..10f14b09d5 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2HuffmanAllocator.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2HuffmanAllocator.java @@ -42,7 +42,7 @@ final class Bzip2HuffmanAllocator { i = Math.max(nodesToMove - 1, i); while (k > i + 1) { - int temp = i + k >> 1; + int temp = i + k >>> 1; if (array[temp] % length > limit) { k = temp; } else { diff --git a/codec/src/main/java/io/netty/handler/codec/compression/JZlibDecoder.java b/codec/src/main/java/io/netty/handler/codec/compression/JZlibDecoder.java index 924cbda887..1c20dc0596 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/JZlibDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/JZlibDecoder.java @@ -31,7 +31,7 @@ public class JZlibDecoder extends ZlibDecoder { /** * Creates a new instance with the default wrapper ({@link ZlibWrapper#ZLIB}). * - * @throws CompressionException if failed to initialize zlib + * @throws DecompressionException if failed to initialize zlib */ public JZlibDecoder() { this(ZlibWrapper.ZLIB); @@ -40,7 +40,7 @@ public class JZlibDecoder extends ZlibDecoder { /** * Creates a new instance with the specified wrapper. * - * @throws CompressionException if failed to initialize zlib + * @throws DecompressionException if failed to initialize zlib */ public JZlibDecoder(ZlibWrapper wrapper) { if (wrapper == null) { @@ -58,7 +58,7 @@ public class JZlibDecoder extends ZlibDecoder { * is always {@link ZlibWrapper#ZLIB} because it is the only format that * supports the preset dictionary. * - * @throws CompressionException if failed to initialize zlib + * @throws DecompressionException if failed to initialize zlib */ public JZlibDecoder(byte[] dictionary) { if (dictionary == null) { diff --git a/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java b/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java index dd5a2cb2dc..c95fb406ea 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java @@ -29,7 +29,6 @@ import io.netty.util.internal.EmptyArrays; import java.util.concurrent.TimeUnit; - /** * Compresses a {@link ByteBuf} using the deflate algorithm. */ 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 a35f48fda1..26471efa1f 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 @@ -24,7 +24,6 @@ import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; - /** * Decompress a {@link ByteBuf} using the inflate algorithm. */ @@ -249,14 +248,14 @@ public class JdkZlibDecoder extends ZlibDecoder { int magic1 = in.readByte(); if (magic0 != 31) { - throw new CompressionException("Input is not in the GZIP format"); + throw new DecompressionException("Input is not in the GZIP format"); } crc.update(magic0); crc.update(magic1); int method = in.readUnsignedByte(); if (method != Deflater.DEFLATED) { - throw new CompressionException("Unsupported compression method " + throw new DecompressionException("Unsupported compression method " + method + " in the GZIP header"); } crc.update(method); @@ -265,7 +264,7 @@ public class JdkZlibDecoder extends ZlibDecoder { crc.update(flags); if ((flags & FRESERVED) != 0) { - throw new CompressionException( + throw new DecompressionException( "Reserved flags are set in the GZIP header"); } @@ -360,7 +359,7 @@ public class JdkZlibDecoder extends ZlibDecoder { } int readLength = inflater.getTotalOut(); if (dataLength != readLength) { - throw new CompressionException( + throw new DecompressionException( "Number of bytes mismatch. Expected: " + dataLength + ", Got: " + readLength); } return true; @@ -373,7 +372,7 @@ public class JdkZlibDecoder extends ZlibDecoder { } long readCrc = crc.getValue(); if (crcValue != readCrc) { - throw new CompressionException( + throw new DecompressionException( "CRC value missmatch. Expected: " + crcValue + ", Got: " + readCrc); } } diff --git a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java index b4faa35547..6b77061608 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java @@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit; import java.util.zip.CRC32; import java.util.zip.Deflater; - /** * Compresses a {@link ByteBuf} using the deflate algorithm. */ diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java b/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java index 1d61d0c119..4b9a7836ea 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java @@ -24,7 +24,7 @@ import io.netty.buffer.ByteBufUtil; * * See http://code.google.com/p/snappy/source/browse/trunk/format_description.txt */ -public class Snappy { +class Snappy { private static final int MAX_HT_SIZE = 1 << 14; private static final int MIN_COMPRESSIBLE_BYTES = 15; diff --git a/codec/src/main/java/io/netty/handler/codec/compression/SnappyFramedDecoder.java b/codec/src/main/java/io/netty/handler/codec/compression/SnappyFramedDecoder.java index f3dee9a8a0..7832be3332 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/SnappyFramedDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/SnappyFramedDecoder.java @@ -36,7 +36,8 @@ import java.util.List; * set to {@code true}. */ public class SnappyFramedDecoder extends ByteToMessageDecoder { - enum ChunkType { + + private enum ChunkType { STREAM_IDENTIFIER, COMPRESSED_DATA, UNCOMPRESSED_DATA, @@ -45,6 +46,7 @@ public class SnappyFramedDecoder extends ByteToMessageDecoder { } private static final byte[] SNAPPY = { 's', 'N', 'a', 'P', 'p', 'Y' }; + private static final int MAX_UNCOMPRESSED_DATA_SIZE = 65536 + 4; private final Snappy snappy = new Snappy(); private final boolean validateChecksums; @@ -83,7 +85,7 @@ public class SnappyFramedDecoder extends ByteToMessageDecoder { try { int idx = in.readerIndex(); - final int inSize = in.writerIndex() - idx; + final int inSize = in.readableBytes(); if (inSize < 4) { // We need to be at least able to read the chunk type identifier (one byte), // and the length of the chunk (3 bytes) in order to proceed @@ -136,7 +138,7 @@ public class SnappyFramedDecoder extends ByteToMessageDecoder { if (!started) { throw new DecompressionException("Received UNCOMPRESSED_DATA tag before STREAM_IDENTIFIER"); } - if (chunkLength > 65536 + 4) { + if (chunkLength > MAX_UNCOMPRESSED_DATA_SIZE) { throw new DecompressionException("Received UNCOMPRESSED_DATA larger than 65540 bytes"); } @@ -193,7 +195,7 @@ public class SnappyFramedDecoder extends ByteToMessageDecoder { * @param type The tag byte extracted from the stream * @return The appropriate {@link ChunkType}, defaulting to {@link ChunkType#RESERVED_UNSKIPPABLE} */ - static ChunkType mapChunkType(byte type) { + private static ChunkType mapChunkType(byte type) { if (type == 0) { return ChunkType.COMPRESSED_DATA; } else if (type == 1) { diff --git a/codec/src/main/java/io/netty/handler/codec/compression/ZlibUtil.java b/codec/src/main/java/io/netty/handler/codec/compression/ZlibUtil.java index 09eb42c8b8..cace66b708 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/ZlibUtil.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/ZlibUtil.java @@ -32,8 +32,8 @@ final class ZlibUtil { throw deflaterException(z, message, resultCode); } - static CompressionException inflaterException(Inflater z, String message, int resultCode) { - return new CompressionException(message + " (" + resultCode + ')' + (z.msg != null? ": " + z.msg : "")); + static DecompressionException inflaterException(Inflater z, String message, int resultCode) { + return new DecompressionException(message + " (" + resultCode + ')' + (z.msg != null? ": " + z.msg : "")); } static CompressionException deflaterException(Deflater z, String message, int resultCode) {