@@ -20,7 +20,7 @@ use mucell::MuCell;
20
20
use uany:: { UnsafeAnyExt } ;
21
21
use unicase:: UniCase ;
22
22
23
- use { http, HttpResult } ;
23
+ use { http, HttpResult , HttpError } ;
24
24
25
25
pub use self :: shared:: { Encoding , QualityItem , qitem} ;
26
26
pub use self :: common:: * ;
@@ -118,6 +118,10 @@ pub struct Headers {
118
118
data : HashMap < HeaderName , MuCell < Item > >
119
119
}
120
120
121
+ // To prevent DOS from a server sending a never ending header.
122
+ // The value was copied from curl.
123
+ const MAX_HEADERS_LENGTH : u32 = 100 * 1024 ;
124
+
121
125
impl Headers {
122
126
123
127
/// Creates a new, empty headers map.
@@ -130,10 +134,16 @@ impl Headers {
130
134
#[ doc( hidden) ]
131
135
pub fn from_raw < R : Reader > ( rdr : & mut R ) -> HttpResult < Headers > {
132
136
let mut headers = Headers :: new ( ) ;
137
+ let mut count = 0u32 ;
133
138
loop {
134
139
match try!( http:: read_header ( rdr) ) {
135
140
Some ( ( name, value) ) => {
136
141
debug ! ( "raw header: {:?}={:?}" , name, & value[ ] ) ;
142
+ count += ( name. len ( ) + value. len ( ) ) as u32 ;
143
+ if count > MAX_HEADERS_LENGTH {
144
+ debug ! ( "Max header size reached, aborting" ) ;
145
+ return Err ( HttpError :: HttpHeaderError )
146
+ }
137
147
let name = UniCase ( Owned ( name) ) ;
138
148
let mut item = match headers. data . entry ( name) {
139
149
Entry :: Vacant ( entry) => entry. insert ( MuCell :: new ( Item :: raw ( vec ! [ ] ) ) ) ,
0 commit comments