@@ -41,9 +41,14 @@ public class HttpGenerator
41
41
private static final Logger LOG = LoggerFactory .getLogger (HttpGenerator .class );
42
42
43
43
public static final boolean __STRICT = Boolean .getBoolean ("org.eclipse.jetty.http.HttpGenerator.STRICT" );
44
-
45
44
private static final byte [] __colon_space = new byte []{':' , ' ' };
46
45
public static final MetaData .Response CONTINUE_100_INFO = new MetaData .Response (100 , null , HttpVersion .HTTP_1_1 , HttpFields .EMPTY );
46
+ private static final Index <Boolean > ASSUMED_CONTENT_METHODS = new Index .Builder <Boolean >()
47
+ .caseSensitive (false )
48
+ .with (HttpMethod .POST .asString (), Boolean .TRUE )
49
+ .with (HttpMethod .PUT .asString (), Boolean .TRUE )
50
+ .build ();
51
+ public static final int CHUNK_SIZE = 12 ;
47
52
48
53
// states
49
54
public enum State
@@ -68,25 +73,14 @@ public enum Result
68
73
DONE // The current phase of generation is complete
69
74
}
70
75
71
- // other statics
72
- public static final int CHUNK_SIZE = 12 ;
73
-
74
76
private State _state = State .START ;
75
77
private EndOfContent _endOfContent = EndOfContent .UNKNOWN_CONTENT ;
76
78
private MetaData _info ;
77
-
78
79
private long _contentPrepared = 0 ;
79
80
private boolean _noContentResponse = false ;
80
81
private Boolean _persistent = null ;
81
-
82
- private static final Index <Boolean > ASSUMED_CONTENT_METHODS = new Index .Builder <Boolean >()
83
- .caseSensitive (false )
84
- .with (HttpMethod .POST .asString (), Boolean .TRUE )
85
- .with (HttpMethod .PUT .asString (), Boolean .TRUE )
86
- .build ();
87
-
88
- // data
89
82
private boolean _needCRLF = false ;
83
+ private int _maxHeaderBytes ;
90
84
91
85
public HttpGenerator ()
92
86
{
@@ -103,6 +97,16 @@ public void reset()
103
97
_needCRLF = false ;
104
98
}
105
99
100
+ public int getMaxHeaderBytes ()
101
+ {
102
+ return _maxHeaderBytes ;
103
+ }
104
+
105
+ public void setMaxHeaderBytes (int maxHeaderBytes )
106
+ {
107
+ _maxHeaderBytes = maxHeaderBytes ;
108
+ }
109
+
106
110
public State getState ()
107
111
{
108
112
return _state ;
@@ -594,28 +598,28 @@ private void generateHeaders(ByteBuffer header, ByteBuffer content, boolean last
594
598
HttpField field = fields .getField (f );
595
599
HttpHeader h = field .getHeader ();
596
600
if (h == null )
601
+ {
597
602
putTo (field , header );
603
+ }
598
604
else
599
605
{
600
606
switch (h )
601
607
{
602
- case CONTENT_LENGTH :
608
+ case CONTENT_LENGTH ->
609
+ {
603
610
if (contentLength < 0 )
604
611
contentLength = field .getLongValue ();
605
612
else if (contentLength != field .getLongValue ())
606
613
throw new HttpException .RuntimeException (INTERNAL_SERVER_ERROR_500 , String .format ("Incorrect Content-Length %d!=%d" , contentLength , field .getLongValue ()));
607
614
contentLengthField = true ;
608
- break ;
609
-
610
- case CONTENT_TYPE :
615
+ }
616
+ case CONTENT_TYPE ->
611
617
{
612
618
// write the field to the header
613
619
contentType = true ;
614
620
putTo (field , header );
615
- break ;
616
621
}
617
-
618
- case TRANSFER_ENCODING :
622
+ case TRANSFER_ENCODING ->
619
623
{
620
624
if (http11 )
621
625
{
@@ -627,10 +631,8 @@ else if (contentLength != field.getLongValue())
627
631
transferEncoding = transferEncoding .withValues (field .getValues ());
628
632
chunkedHint |= field .contains (HttpHeaderValue .CHUNKED .asString ());
629
633
}
630
- break ;
631
634
}
632
-
633
- case CONNECTION :
635
+ case CONNECTION ->
634
636
{
635
637
// Save to connection field for processing when all other fields are known
636
638
if (connection == null )
@@ -641,13 +643,11 @@ else if (contentLength != field.getLongValue())
641
643
connectionClose |= field .contains (HttpHeaderValue .CLOSE .asString ());
642
644
connectionKeepAlive |= field .contains (HttpHeaderValue .KEEP_ALIVE .asString ());
643
645
connectionUpgrade |= field .contains (HttpHeaderValue .UPGRADE .asString ());
644
- break ;
645
646
}
646
-
647
- default :
648
- putTo (field , header );
647
+ default -> putTo (field , header );
649
648
}
650
649
}
650
+ checkMaxHeaderBytes (header );
651
651
}
652
652
}
653
653
@@ -887,12 +887,23 @@ else if (http10)
887
887
888
888
// end the header.
889
889
header .put (HttpTokens .CRLF );
890
+
891
+ checkMaxHeaderBytes (header );
892
+ }
893
+
894
+ private void checkMaxHeaderBytes (ByteBuffer header )
895
+ {
896
+ int maxHeaderBytes = getMaxHeaderBytes ();
897
+ if (maxHeaderBytes > 0 && header .position () > maxHeaderBytes )
898
+ throw new BufferOverflowException ();
890
899
}
891
900
892
901
private static void putContentLength (ByteBuffer header , long contentLength )
893
902
{
894
903
if (contentLength == 0 )
904
+ {
895
905
header .put (CONTENT_LENGTH_0 );
906
+ }
896
907
else
897
908
{
898
909
header .put (HttpHeader .CONTENT_LENGTH .getBytesColonSpace ());
0 commit comments