codec-http2: Better keep track of nameLength in HpackDecoder.decode

Motivation:

http/2 counts header sizes somewhat inconsistently.  Sometimes, headers
which are substantively less than the header list size will be measured
as longer than the header list size.

Modifications:

Keep better track of the nameLength of a given name, so that we don't
accidentally end up reusing a nameLength.

Result:

More consistent measurement of header list size.

Fixes #7511.
This commit is contained in:
Moses Nakamura 2017-12-18 20:41:09 -05:00 committed by Scott Mitchell
parent f9888acfdd
commit 94ab0dc442
2 changed files with 25 additions and 0 deletions

View File

@ -162,6 +162,7 @@ final class HpackDecoder {
default:
// Index was stored as the prefix
name = readName(index);
nameLength = name.length();
state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
}
} else if ((b & 0x20) == 0x20) {
@ -187,6 +188,7 @@ final class HpackDecoder {
default:
// Index was stored as the prefix
name = readName(index);
nameLength = name.length();
state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
}
}
@ -205,6 +207,7 @@ final class HpackDecoder {
case READ_INDEXED_HEADER_NAME:
// Header Name matches an entry in the Header Table
name = readName(decodeULE128(in, index));
nameLength = name.length();
state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
break;

View File

@ -455,4 +455,26 @@ public class HpackDecoderTest {
in.release();
}
}
@Test
public void testDecodeCountsNamesOnlyOnce() throws Http2Exception {
ByteBuf in = Unpooled.buffer(200);
try {
hpackDecoder.setMaxHeaderListSize(3500, 4000);
HpackEncoder hpackEncoder = new HpackEncoder(true);
// encode headers that are slightly larger than maxHeaderListSize
// but smaller than maxHeaderListSizeGoAway
Http2Headers toEncode = new DefaultHttp2Headers();
toEncode.add(String.format("%03000d", 0).replace('0', 'f'), "value");
toEncode.add("accept", "value");
hpackEncoder.encodeHeaders(1, in, toEncode, NEVER_SENSITIVE);
Http2Headers decoded = new DefaultHttp2Headers();
hpackDecoder.decode(1, in, decoded);
assertEquals(2, decoded.size());
} finally {
in.release();
}
}
}