Skip to content

Commit ce4204a

Browse files
committed
Upgrade http-parser
Fixes, among other things, a header overflow attack.
1 parent 9874412 commit ce4204a

File tree

4 files changed

+121
-31
lines changed

4 files changed

+121
-31
lines changed

deps/http_parser/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
OPT_DEBUG=-O0 -g -Wall -Wextra -Werror
2-
OPT_FAST=-O3 -DHTTP_PARSER_STRICT=0
1+
OPT_DEBUG=-O0 -g -Wall -Wextra -Werror -I.
2+
OPT_FAST=-O3 -DHTTP_PARSER_STRICT=0 -I.
33

44

55
test: test_debug

deps/http_parser/http_parser.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,10 @@ static inline int message_complete_callback (http_parser *parser)
106106
#define KEEP_ALIVE "keep-alive"
107107
#define CLOSE "close"
108108

109-
110109
static const unsigned char lowcase[] =
111110
"\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"
112111
"\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_"
114113
"\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
115114
"\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"
116115
"\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
199198
, s_header_almost_done
200199

201200
, 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+
*/
203205
, s_chunk_size_start
204206
, s_chunk_size
205207
, s_chunk_size_almost_done
@@ -212,6 +214,8 @@ enum state
212214
, s_body_identity_eof
213215
};
214216

217+
#define PARSING_HEADER(state) (state <= s_headers_almost_done)
218+
215219
enum header_states
216220
{ h_general = 0
217221
, h_C
@@ -262,12 +266,13 @@ size_t http_parser_execute (http_parser *parser,
262266
size_t len)
263267
{
264268
char c, ch;
265-
const char *p, *pe;
269+
const char *p = data, *pe;
266270
ssize_t to_read;
267271

268272
enum state state = parser->state;
269273
enum header_states header_state = parser->header_state;
270274
size_t index = parser->index;
275+
size_t nread = parser->nread;
271276

272277
if (len == 0) {
273278
if (state == s_body_identity_eof) {
@@ -285,6 +290,12 @@ size_t http_parser_execute (http_parser *parser,
285290

286291
for (p=data, pe=data+len; p != pe; p++) {
287292
ch = *p;
293+
294+
if (++nread > HTTP_MAX_HEADER_SIZE && PARSING_HEADER(state)) {
295+
/* Buffer overflow attack */
296+
goto error;
297+
}
298+
288299
switch (state) {
289300

290301
case s_dead:
@@ -442,6 +453,8 @@ size_t http_parser_execute (http_parser *parser,
442453

443454
case s_start_req:
444455
{
456+
if (ch == CR || ch == LF)
457+
break;
445458
parser->flags = 0;
446459
parser->content_length = -1;
447460

@@ -739,6 +752,9 @@ size_t http_parser_execute (http_parser *parser,
739752
if (USUAL(ch)) break;
740753

741754
switch (ch) {
755+
case '?':
756+
// allow extra '?' in query string
757+
break;
742758
case ' ':
743759
CALLBACK(url);
744760
CALLBACK(query_string);
@@ -1262,6 +1278,7 @@ size_t http_parser_execute (http_parser *parser,
12621278
}
12631279

12641280
parser->body_read = 0;
1281+
nread = 0;
12651282

12661283
CALLBACK2(headers_complete);
12671284

@@ -1421,6 +1438,7 @@ size_t http_parser_execute (http_parser *parser,
14211438
parser->state = state;
14221439
parser->header_state = header_state;
14231440
parser->index = index;
1441+
parser->nread = nread;
14241442

14251443
return len;
14261444

@@ -1455,6 +1473,8 @@ http_parser_init (http_parser *parser, enum http_parser_type t)
14551473
{
14561474
parser->type = t;
14571475
parser->state = (t == HTTP_REQUEST ? s_start_req : s_start_res);
1476+
parser->nread = 0;
1477+
14581478
parser->on_message_begin = NULL;
14591479
parser->on_path = NULL;
14601480
parser->on_query_string = NULL;

deps/http_parser/http_parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ extern "C" {
3838
# define HTTP_PARSER_STRICT 0
3939
#endif
4040

41+
/* Maximium header size allowed */
42+
#define HTTP_MAX_HEADER_SIZE (80*1024)
43+
4144
typedef struct http_parser http_parser;
4245

4346
/* Callbacks should return non-zero to indicate an error. The parse will
@@ -85,6 +88,7 @@ struct http_parser {
8588

8689
char flags;
8790

91+
size_t nread;
8892
ssize_t body_read;
8993
ssize_t content_length;
9094

0 commit comments

Comments
 (0)