diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java index 9b8ff3f04c..801900c487 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java @@ -228,6 +228,11 @@ final class Bzip2BlockDecompressor { bwtBlock[bwtBlockLength++] = nextByte; } } + if (bwtBlockLength > MAX_BLOCK_LENGTH) { + throw new DecompressionException("block length exceeds max block length: " + + bwtBlockLength + " > " + MAX_BLOCK_LENGTH); + } + this.bwtBlockLength = bwtBlockLength; initialiseInverseBWT(); return true; diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java index ba8fee54d3..087f45faa0 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java @@ -49,6 +49,8 @@ final class Bzip2Constants { static final int MIN_BLOCK_SIZE = 1; static final int MAX_BLOCK_SIZE = 9; + static final int MAX_BLOCK_LENGTH = MAX_BLOCK_SIZE * BASE_BLOCK_SIZE; + /** * Maximum possible Huffman alphabet size. */ diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java index f3b54fd6ab..f28bad932b 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java @@ -289,26 +289,27 @@ public class Bzip2Decoder extends ByteToMessageDecoder { } final int blockLength = blockDecompressor.blockLength(); - final ByteBuf uncompressed = ctx.alloc().buffer(blockLength); - boolean success = false; + ByteBuf uncompressed = ctx.alloc().buffer(blockLength); try { int uncByte; while ((uncByte = blockDecompressor.read()) >= 0) { uncompressed.writeByte(uncByte); } - + // We did read all the data, lets reset the state and do the CRC check. + currentState = State.INIT_BLOCK; int currentBlockCRC = blockDecompressor.checkCRC(); streamCRC = (streamCRC << 1 | streamCRC >>> 31) ^ currentBlockCRC; ctx.fireChannelRead(uncompressed); - success = true; + uncompressed = null; } finally { - if (!success) { + if (uncompressed != null) { uncompressed.release(); } } - currentState = State.INIT_BLOCK; - break; + // Return here so the ByteBuf that was put in the List will be forwarded to the user and so can be + // released as soon as possible. + return; case EOF: in.skipBytes(in.readableBytes()); return;