diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java index 5b09055d23b..0071fcef539 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java @@ -466,18 +466,28 @@ private static IllegalArgumentException notEnoughDataException(ByteBuf in) { * Visible for testing only! */ static int decodeULE128(ByteBuf in, int result) throws Http2Exception { - final int readerIndex = in.readerIndex(); - final long v = decodeULE128(in, (long) result); - if (v > Integer.MAX_VALUE) { - // the maximum value that can be represented by a signed 32 bit number is: - // [0x1,0x7f] + 0x7f + (0x7f << 7) + (0x7f << 14) + (0x7f << 21) + (0x6 << 28) - // OR - // 0x0 + 0x7f + (0x7f << 7) + (0x7f << 14) + (0x7f << 21) + (0x7 << 28) - // we should reset the readerIndex if we overflowed the int type. - in.readerIndex(readerIndex); - throw DECODE_ULE_128_TO_INT_DECOMPRESSION_EXCEPTION; + assert result <= 0x7f && result >= 0; + final boolean resultStartedAtZero = result == 0; + final int writerIndex = in.writerIndex(); + for (int readerIndex = in.readerIndex(), shift = 0; readerIndex < writerIndex; ++readerIndex, shift += 7) { + byte b = in.getByte(readerIndex); + if (shift == 28 && ((b & 0x80) != 0 || !resultStartedAtZero && b > 6 || resultStartedAtZero && b > 7)) { + // the maximum value that can be represented by a signed 32 bit number is: + // [0x1,0x7f] + 0x7f + (0x7f << 7) + (0x7f << 14) + (0x7f << 21) + (0x6 << 28) + // OR + // 0x0 + 0x7f + (0x7f << 7) + (0x7f << 14) + (0x7f << 21) + (0x7 << 28) + // this means any more shifts will result in overflow so we should break out and throw an error. + throw DECODE_ULE_128_TO_INT_DECOMPRESSION_EXCEPTION; + } + + if ((b & 0x80) == 0) { + in.readerIndex(readerIndex + 1); + return result + ((b & 0x7F) << shift); + } + result += (b & 0x7F) << shift; } - return (int) v; + + throw DECODE_ULE_128_DECOMPRESSION_EXCEPTION; } /**