Skip to content

Commit 5958324

Browse files
committed
Align processing of trailer headers with standard processing
1 parent 529370e commit 5958324

4 files changed

Lines changed: 26 additions & 2 deletions

File tree

java/org/apache/coyote/http11/Http11InputBuffer.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,12 @@ private boolean fill(boolean block) throws IOException {
830830
*/
831831
private HeaderParseStatus parseHeader() throws IOException {
832832

833+
/*
834+
* Implementation note: Any changes to this method probably need to be echoed in
835+
* ChunkedInputFilter.parseHeader(). Why not use a common implementation? In short, this code uses non-blocking
836+
* reads whereas ChunkedInputFilter using blocking reads. The code is just different enough that a common
837+
* implementation wasn't viewed as practical.
838+
*/
833839
while (headerParsePos == HeaderParsePosition.HEADER_START) {
834840

835841
// Read new bytes if needed
@@ -972,7 +978,7 @@ private HeaderParseStatus parseHeader() throws IOException {
972978
} else if (prevChr == Constants.CR) {
973979
// Invalid value - also need to delete header
974980
return skipLine(true);
975-
} else if (chr != Constants.HT && HttpParser.isControl(chr)) {
981+
} else if (HttpParser.isControl(chr) && chr != Constants.HT) {
976982
// Invalid value - also need to delete header
977983
return skipLine(true);
978984
} else if (chr == Constants.SP || chr == Constants.HT) {

java/org/apache/coyote/http11/filters/ChunkedInputFilter.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.coyote.http11.InputFilter;
3131
import org.apache.tomcat.util.buf.ByteChunk;
3232
import org.apache.tomcat.util.buf.HexUtils;
33+
import org.apache.tomcat.util.http.parser.HttpParser;
3334
import org.apache.tomcat.util.net.ApplicationBufferHandler;
3435
import org.apache.tomcat.util.res.StringManager;
3536

@@ -443,6 +444,13 @@ protected void parseEndChunk() throws IOException {
443444

444445
private boolean parseHeader() throws IOException {
445446

447+
/*
448+
* Implementation note: Any changes to this method probably need to be echoed in
449+
* Http11InputBuffer.parseHeader(). Why not use a common implementation? In short, this code uses blocking
450+
* reads whereas Http11InputBuffer using non-blocking reads. The code is just different enough that a common
451+
* implementation wasn't viewed as practical.
452+
*/
453+
446454
Map<String,String> headers = request.getTrailerFields();
447455

448456
byte chr = 0;
@@ -489,6 +497,9 @@ private boolean parseHeader() throws IOException {
489497

490498
if (chr == Constants.COLON) {
491499
colon = true;
500+
} else if (!HttpParser.isToken(chr)) {
501+
// Non-token characters are illegal in header names
502+
throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderName"));
492503
} else {
493504
trailingHeaders.append(chr);
494505
}
@@ -550,7 +561,9 @@ private boolean parseHeader() throws IOException {
550561
if (chr == Constants.CR || chr == Constants.LF) {
551562
parseCRLF(true);
552563
eol = true;
553-
} else if (chr == Constants.SP) {
564+
} else if (HttpParser.isControl(chr) && chr != Constants.HT) {
565+
throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderValue"));
566+
} else if (chr == Constants.SP || chr == Constants.HT) {
554567
trailingHeaders.append(chr);
555568
} else {
556569
trailingHeaders.append(chr);

java/org/apache/coyote/http11/filters/LocalStrings.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR)
2424
chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF)
2525
chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read)
2626
chunkedInputFilter.invalidHeader=Invalid chunk header
27+
chunkedInputFilter.invalidTrailerHeaderName=Invalid trailer header name (non-token character in name)
28+
chunkedInputFilter.invalidTrailerHeaderValue=Invalid trailer header value (control character in value)
2729
chunkedInputFilter.maxExtension=maxExtensionSize exceeded
2830
chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
2931

webapps/docs/changelog.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@
160160
Improve statistics collection for upgraded connections under load.
161161
(remm)
162162
</fix>
163+
<fix>
164+
Align validation of HTTP trailer fields with standard fields. (markt)
165+
</fix>
163166
</changelog>
164167
</subsection>
165168
<subsection name="Jasper">

0 commit comments

Comments
 (0)