Update hpack Decoder CTOR to allow for overflow in maxHeaderList size, as we do when we apply our ack'ed settings
This prevents us from having the first request, that hasn't ack'ed the setting causing a GOAWAY when we'd would be under the maxHeaderListSizeGoAway that would have been set after the settings ack.
This commit is contained in:
parent
e9fa40d770
commit
907726988d
@ -149,8 +149,7 @@ public class DefaultHttp2ConnectionDecoder implements Http2ConnectionDecoder {
|
|||||||
* @return the threshold in bytes which should trigger a {@code GO_AWAY} if a set of headers exceeds this amount.
|
* @return the threshold in bytes which should trigger a {@code GO_AWAY} if a set of headers exceeds this amount.
|
||||||
*/
|
*/
|
||||||
protected long calculateMaxHeaderListSizeGoAway(long maxHeaderListSize) {
|
protected long calculateMaxHeaderListSizeGoAway(long maxHeaderListSize) {
|
||||||
// This is equivalent to `maxHeaderListSize * 1.25` but we avoid floating point multiplication.
|
return Http2CodecUtil.calculateMaxHeaderListSizeGoAway(maxHeaderListSize);
|
||||||
return maxHeaderListSize + (maxHeaderListSize >>> 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int unconsumedBytes(Http2Stream stream) {
|
private int unconsumedBytes(Http2Stream stream) {
|
||||||
|
@ -112,6 +112,18 @@ public final class Http2CodecUtil {
|
|||||||
public static final long DEFAULT_HEADER_LIST_SIZE = 8192;
|
public static final long DEFAULT_HEADER_LIST_SIZE = 8192;
|
||||||
public static final int DEFAULT_MAX_FRAME_SIZE = MAX_FRAME_SIZE_LOWER_BOUND;
|
public static final int DEFAULT_MAX_FRAME_SIZE = MAX_FRAME_SIZE_LOWER_BOUND;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the threshold in bytes which should trigger a {@code GO_AWAY} if a set of headers exceeds this amount.
|
||||||
|
* @param maxHeaderListSize
|
||||||
|
* <a href="https://tools.ietf.org/html/rfc7540#section-6.5.2">SETTINGS_MAX_HEADER_LIST_SIZE</a> for the local
|
||||||
|
* endpoint.
|
||||||
|
* @return the threshold in bytes which should trigger a {@code GO_AWAY} if a set of headers exceeds this amount.
|
||||||
|
*/
|
||||||
|
public static long calculateMaxHeaderListSizeGoAway(long maxHeaderListSize) {
|
||||||
|
// This is equivalent to `maxHeaderListSize * 1.25` but we avoid floating point multiplication.
|
||||||
|
return maxHeaderListSize + (maxHeaderListSize >>> 2);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if the stream is an outbound stream.
|
* Returns {@code true} if the stream is an outbound stream.
|
||||||
*
|
*
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
package io.netty.handler.codec.http2.internal.hpack;
|
package io.netty.handler.codec.http2.internal.hpack;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.handler.codec.http2.Http2CodecUtil;
|
||||||
import io.netty.handler.codec.http2.Http2Exception;
|
import io.netty.handler.codec.http2.Http2Exception;
|
||||||
import io.netty.handler.codec.http2.Http2Headers;
|
import io.netty.handler.codec.http2.Http2Headers;
|
||||||
import io.netty.handler.codec.http2.internal.hpack.HpackUtil.IndexType;
|
import io.netty.handler.codec.http2.internal.hpack.HpackUtil.IndexType;
|
||||||
@ -106,7 +107,9 @@ public final class Decoder {
|
|||||||
* for testing but violate the RFC if used outside the scope of testing.
|
* for testing but violate the RFC if used outside the scope of testing.
|
||||||
*/
|
*/
|
||||||
Decoder(long maxHeaderListSize, int initialHuffmanDecodeCapacity, int maxHeaderTableSize) {
|
Decoder(long maxHeaderListSize, int initialHuffmanDecodeCapacity, int maxHeaderTableSize) {
|
||||||
this.maxHeaderListSize = maxHeaderListSizeGoAway = checkPositive(maxHeaderListSize, "maxHeaderListSize");
|
this.maxHeaderListSize = checkPositive(maxHeaderListSize, "maxHeaderListSize");
|
||||||
|
this.maxHeaderListSizeGoAway = Http2CodecUtil.calculateMaxHeaderListSizeGoAway(maxHeaderListSize);
|
||||||
|
|
||||||
maxDynamicTableSize = encoderMaxDynamicTableSize = maxHeaderTableSize;
|
maxDynamicTableSize = encoderMaxDynamicTableSize = maxHeaderTableSize;
|
||||||
maxDynamicTableSizeChangeRequired = false;
|
maxDynamicTableSizeChangeRequired = false;
|
||||||
dynamicTable = new DynamicTable(maxHeaderTableSize);
|
dynamicTable = new DynamicTable(maxHeaderTableSize);
|
||||||
|
@ -84,6 +84,21 @@ public class DefaultHttp2HeadersDecoderTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decodeLargerThanHeaderListSizeButLessThanGoAwayWithInitialDecoderSettings() throws Exception {
|
||||||
|
ByteBuf buf = encode(b(":method"), b("GET"), b("test_header"),
|
||||||
|
b(String.format("%09000d", 0).replace('0', 'A')));
|
||||||
|
final int streamId = 1;
|
||||||
|
try {
|
||||||
|
decoder.decodeHeaders(streamId, buf);
|
||||||
|
fail();
|
||||||
|
} catch (Http2Exception.HeaderListSizeException e) {
|
||||||
|
assertEquals(streamId, e.streamId());
|
||||||
|
} finally {
|
||||||
|
buf.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void decodeLargerThanHeaderListSizeGoAway() throws Exception {
|
public void decodeLargerThanHeaderListSizeGoAway() throws Exception {
|
||||||
decoder.maxHeaderListSize(MIN_HEADER_LIST_SIZE, MIN_HEADER_LIST_SIZE);
|
decoder.maxHeaderListSize(MIN_HEADER_LIST_SIZE, MIN_HEADER_LIST_SIZE);
|
||||||
|
Loading…
Reference in New Issue
Block a user