Skip to content

Commit 977661f

Browse files
authored
Merge commit from fork
Motivation: RFC9112 specified that chunked must be the last encoding so we should verify this. Modifications: - Add code to validate that chunked is the last encoding and if not fail decoding - Add unit test Result: More strictly follow RFC
1 parent b7f7bfc commit 977661f

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.netty.util.internal.SystemPropertyUtil;
3030
import io.netty.util.internal.ThrowableUtil;
3131

32+
import java.util.Iterator;
3233
import java.util.List;
3334
import java.util.concurrent.atomic.AtomicBoolean;
3435

@@ -846,8 +847,28 @@ private State readHeaders(ByteBuf buffer) {
846847
}
847848
if (HttpUtil.isTransferEncodingChunked(message)) {
848849
this.chunked = true;
849-
if (!contentLengthFields.isEmpty() && message.protocolVersion() == HttpVersion.HTTP_1_1) {
850-
handleTransferEncodingChunkedWithContentLength(message);
850+
if (message.protocolVersion() == HttpVersion.HTTP_1_1) {
851+
Iterator<? extends CharSequence> encodingIt =
852+
message.headers().valueCharSequenceIterator(HttpHeaderNames.TRANSFER_ENCODING);
853+
// Validate that chunked is the last encoding.
854+
// See https://datatracker.ietf.org/doc/html/rfc9112#name-message-body-length
855+
CharSequence v = null;
856+
while (encodingIt.hasNext()) {
857+
v = encodingIt.next();
858+
}
859+
final int vLen = v.length();
860+
final int chunkedValueLength = HttpHeaderValues.CHUNKED.length();
861+
// We only need to validate if we have more then the chunked value length contained as otherwise
862+
// we know it is only chunked.
863+
if (vLen > chunkedValueLength && !AsciiString.regionMatches(v, true, vLen - chunkedValueLength,
864+
HttpHeaderValues.CHUNKED,0, chunkedValueLength)) {
865+
throw new IllegalArgumentException(
866+
"chunked must be the last encoding present in the Transfer-Encoding header");
867+
868+
}
869+
if (!contentLengthFields.isEmpty()) {
870+
handleTransferEncodingChunkedWithContentLength(message);
871+
}
851872
}
852873
return State.READ_CHUNK_SIZE;
853874
}

codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,16 @@ public void testMultipleContentLengthHeadersWithFolding() {
677677
testInvalidHeaders0(requestStr);
678678
}
679679

680+
@Test
681+
public void testChunkedNotLastInTransferEncoding() {
682+
String requestStr = "GET /some/path HTTP/1.1\r\n" +
683+
"Transfer-Encoding: chunked, identity\r\n" +
684+
"Content-Length: 1\r\n" +
685+
"Host: netty.io\r\n\r\n" +
686+
"a";
687+
testInvalidHeaders0(requestStr);
688+
}
689+
680690
@Test
681691
public void testContentLengthAndTransferEncodingHeadersWithVerticalTab() {
682692
testContentLengthAndTransferEncodingHeadersWithInvalidSeparator((char) 0x0b, false);

0 commit comments

Comments
 (0)