@@ -582,17 +582,42 @@ public void run () {
582
582
start = space +1 ;
583
583
String version = requestLine .substring (start );
584
584
Headers headers = req .headers ();
585
- String s = headers .getFirst ("Transfer-encoding" );
585
+ /* check key for illegal characters */
586
+ for (var k : headers .keySet ()) {
587
+ if (!isValidHeaderKey (k )) {
588
+ reject (Code .HTTP_BAD_REQUEST , requestLine ,
589
+ "Header key contains illegal characters" );
590
+ return ;
591
+ }
592
+ }
593
+ /* checks for unsupported combinations of lengths and encodings */
594
+ if (headers .containsKey ("Content-Length" ) &&
595
+ (headers .containsKey ("Transfer-encoding" ) || headers .get ("Content-Length" ).size () > 1 )) {
596
+ reject (Code .HTTP_BAD_REQUEST , requestLine ,
597
+ "Conflicting or malformed headers detected" );
598
+ return ;
599
+ }
586
600
long clen = 0L ;
587
- if (s !=null && s .equalsIgnoreCase ("chunked" )) {
588
- clen = -1L ;
601
+ String headerValue = null ;
602
+ List <String > teValueList = headers .get ("Transfer-encoding" );
603
+ if (teValueList != null && !teValueList .isEmpty ()) {
604
+ headerValue = teValueList .get (0 );
605
+ }
606
+ if (headerValue != null ) {
607
+ if (headerValue .equalsIgnoreCase ("chunked" ) && teValueList .size () == 1 ) {
608
+ clen = -1L ;
609
+ } else {
610
+ reject (Code .HTTP_NOT_IMPLEMENTED ,
611
+ requestLine , "Unsupported Transfer-Encoding value" );
612
+ return ;
613
+ }
589
614
} else {
590
- s = headers .getFirst ("Content-Length" );
591
- if (s != null ) {
592
- clen = Long .parseLong (s );
615
+ headerValue = headers .getFirst ("Content-Length" );
616
+ if (headerValue != null ) {
617
+ clen = Long .parseLong (headerValue );
593
618
}
594
619
if (clen == 0 ) {
595
- requestCompleted (connection );
620
+ requestCompleted (connection );
596
621
}
597
622
}
598
623
ctx = contexts .findContext (protocol , uri .getPath ());
@@ -907,4 +932,24 @@ static long getTimeMillis(long secs) {
907
932
return secs * 1000 ;
908
933
}
909
934
}
935
+
936
+ /*
937
+ * Validates a RFC 7230 header-key.
938
+ */
939
+ static boolean isValidHeaderKey (String token ) {
940
+ if (token == null ) return false ;
941
+
942
+ boolean isValidChar ;
943
+ char [] chars = token .toCharArray ();
944
+ String validSpecialChars = "!#$%&'*+-.^_`|~" ;
945
+ for (char c : chars ) {
946
+ isValidChar = ((c >= 'a' ) && (c <= 'z' )) ||
947
+ ((c >= 'A' ) && (c <= 'Z' )) ||
948
+ ((c >= '0' ) && (c <= '9' ));
949
+ if (!isValidChar && validSpecialChars .indexOf (c ) == -1 ) {
950
+ return false ;
951
+ }
952
+ }
953
+ return !token .isEmpty ();
954
+ }
910
955
}
0 commit comments