@@ -106,11 +106,10 @@ static inline int message_complete_callback (http_parser *parser)
106
106
#define KEEP_ALIVE "keep-alive"
107
107
#define CLOSE "close"
108
108
109
-
110
109
static const unsigned char lowcase [] =
111
110
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
112
111
"\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0" "0123456789\0\0\0\0\0\0"
113
- "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0 "
112
+ "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0_ "
114
113
"\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
115
114
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
116
115
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
@@ -199,7 +198,10 @@ enum state
199
198
, s_header_almost_done
200
199
201
200
, s_headers_almost_done
202
-
201
+ /* Important: 's_headers_almost_done' must be the last 'header' state. All
202
+ * states beyond this must be 'body' states. It is used for overflow
203
+ * checking. See the PARSING_HEADER() macro.
204
+ */
203
205
, s_chunk_size_start
204
206
, s_chunk_size
205
207
, s_chunk_size_almost_done
@@ -212,6 +214,8 @@ enum state
212
214
, s_body_identity_eof
213
215
};
214
216
217
+ #define PARSING_HEADER (state ) (state <= s_headers_almost_done)
218
+
215
219
enum header_states
216
220
{ h_general = 0
217
221
, h_C
@@ -262,12 +266,13 @@ size_t http_parser_execute (http_parser *parser,
262
266
size_t len )
263
267
{
264
268
char c , ch ;
265
- const char * p , * pe ;
269
+ const char * p = data , * pe ;
266
270
ssize_t to_read ;
267
271
268
272
enum state state = parser -> state ;
269
273
enum header_states header_state = parser -> header_state ;
270
274
size_t index = parser -> index ;
275
+ size_t nread = parser -> nread ;
271
276
272
277
if (len == 0 ) {
273
278
if (state == s_body_identity_eof ) {
@@ -285,6 +290,12 @@ size_t http_parser_execute (http_parser *parser,
285
290
286
291
for (p = data , pe = data + len ; p != pe ; p ++ ) {
287
292
ch = * p ;
293
+
294
+ if (++ nread > HTTP_MAX_HEADER_SIZE && PARSING_HEADER (state )) {
295
+ /* Buffer overflow attack */
296
+ goto error ;
297
+ }
298
+
288
299
switch (state ) {
289
300
290
301
case s_dead :
@@ -442,6 +453,8 @@ size_t http_parser_execute (http_parser *parser,
442
453
443
454
case s_start_req :
444
455
{
456
+ if (ch == CR || ch == LF )
457
+ break ;
445
458
parser -> flags = 0 ;
446
459
parser -> content_length = -1 ;
447
460
@@ -739,6 +752,9 @@ size_t http_parser_execute (http_parser *parser,
739
752
if (USUAL (ch )) break ;
740
753
741
754
switch (ch ) {
755
+ case '?' :
756
+ // allow extra '?' in query string
757
+ break ;
742
758
case ' ' :
743
759
CALLBACK (url );
744
760
CALLBACK (query_string );
@@ -1262,6 +1278,7 @@ size_t http_parser_execute (http_parser *parser,
1262
1278
}
1263
1279
1264
1280
parser -> body_read = 0 ;
1281
+ nread = 0 ;
1265
1282
1266
1283
CALLBACK2 (headers_complete );
1267
1284
@@ -1421,6 +1438,7 @@ size_t http_parser_execute (http_parser *parser,
1421
1438
parser -> state = state ;
1422
1439
parser -> header_state = header_state ;
1423
1440
parser -> index = index ;
1441
+ parser -> nread = nread ;
1424
1442
1425
1443
return len ;
1426
1444
@@ -1455,6 +1473,8 @@ http_parser_init (http_parser *parser, enum http_parser_type t)
1455
1473
{
1456
1474
parser -> type = t ;
1457
1475
parser -> state = (t == HTTP_REQUEST ? s_start_req : s_start_res );
1476
+ parser -> nread = 0 ;
1477
+
1458
1478
parser -> on_message_begin = NULL ;
1459
1479
parser -> on_path = NULL ;
1460
1480
parser -> on_query_string = NULL ;
0 commit comments