Skip to content

Commit

Permalink
Upgrade http-parser
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Jun 24, 2010
1 parent 2c0d91b commit 8825c74
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 194 deletions.
249 changes: 89 additions & 160 deletions deps/http_parser/http_parser.c
Expand Up @@ -77,7 +77,30 @@ do { \
#define CLOSE "close"


static const unsigned char lowcase[] =
static const char *method_strings[] =
{ "DELETE"
, "GET"
, "HEAD"
, "POST"
, "PUT"
, "CONNECT"
, "OPTIONS"
, "TRACE"
, "COPY"
, "LOCK"
, "MKCOL"
, "MOVE"
, "PROPFIND"
, "PROPPATCH"
, "UNLOCK"
, "REPORT"
, "MKACTIVITY"
, "CHECKOUT"
, "MERGE"
};


static const char lowcase[256] =
"\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"
"\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0" "0123456789\0\0\0\0\0\0"
"\0abcdefghijklmnopqrstuvwxyz\0\0\0\0_"
Expand Down Expand Up @@ -248,35 +271,6 @@ enum flags
#endif


#define ngx_str3_cmp(m, c0, c1, c2) \
m[0] == c0 && m[1] == c1 && m[2] == c2

#define ngx_str3Ocmp(m, c0, c1, c2, c3) \
m[0] == c0 && m[2] == c2 && m[3] == c3

#define ngx_str4cmp(m, c0, c1, c2, c3) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3

#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4

#define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5

#define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5 && m[6] == c6

#define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7

#define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 && m[8] == c8


size_t http_parser_execute (http_parser *parser,
const http_parser_settings *settings,
const char *data,
Expand Down Expand Up @@ -327,9 +321,10 @@ size_t http_parser_execute (http_parser *parser,
for (p=data, pe=data+len; p != pe; p++) {
ch = *p;

if (++nread > HTTP_MAX_HEADER_SIZE && PARSING_HEADER(state)) {
if (PARSING_HEADER(state)) {
++nread;
/* Buffer overflow attack */
goto error;
if (nread > HTTP_MAX_HEADER_SIZE) goto error;
}

switch (state) {
Expand All @@ -353,10 +348,7 @@ size_t http_parser_execute (http_parser *parser,
state = s_res_or_resp_H;
else {
parser->type = HTTP_REQUEST;
if (ch < 'A' || 'Z' < ch) goto error;
parser->buffer[0] = ch;
index = 0;
state = s_req_method;
goto start_req_method_assign;
}
break;
}
Expand All @@ -366,12 +358,10 @@ size_t http_parser_execute (http_parser *parser,
parser->type = HTTP_RESPONSE;
state = s_res_HT;
} else {
if (ch < 'A' || 'Z' < ch) goto error;
if (ch != 'E') goto error;
parser->type = HTTP_REQUEST;
parser->method = (enum http_method) 0;
parser->buffer[0] = 'H';
parser->buffer[1] = ch;
index = 1;
parser->method = HTTP_HEAD;
index = 2;
state = s_req_method;
}
break;
Expand Down Expand Up @@ -534,128 +524,64 @@ size_t http_parser_execute (http_parser *parser,

if (ch < 'A' || 'Z' < ch) goto error;

start_req_method_assign:
parser->method = (enum http_method) 0;
index = 0;
parser->buffer[0] = ch;
index = 1;
switch (ch) {
case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
case 'D': parser->method = HTTP_DELETE; break;
case 'G': parser->method = HTTP_GET; break;
case 'H': parser->method = HTTP_HEAD; break;
case 'L': parser->method = HTTP_LOCK; break;
case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE */ break;
case 'O': parser->method = HTTP_OPTIONS; break;
case 'P': parser->method = HTTP_POST; /* or PROPFIND or PROPPATCH or PUT */ break;
case 'R': parser->method = HTTP_REPORT; break;
case 'T': parser->method = HTTP_TRACE; break;
case 'U': parser->method = HTTP_UNLOCK; break;
default: goto error;
}
state = s_req_method;
break;
}

case s_req_method:
if (ch == ' ') {
assert(index+1 < HTTP_PARSER_MAX_METHOD_LEN);
parser->buffer[index+1] = '\0';

switch (index+1) {
case 3:
if (ngx_str3_cmp(parser->buffer, 'G', 'E', 'T')) {
parser->method = HTTP_GET;
break;
}

if (ngx_str3_cmp(parser->buffer, 'P', 'U', 'T')) {
parser->method = HTTP_PUT;
break;
}

break;

case 4:
if (ngx_str4cmp(parser->buffer, 'P', 'O', 'S', 'T')) {
parser->method = HTTP_POST;
break;
}

if (ngx_str4cmp(parser->buffer, 'H', 'E', 'A', 'D')) {
parser->method = HTTP_HEAD;
break;
}

if (ngx_str4cmp(parser->buffer, 'C', 'O', 'P', 'Y')) {
parser->method = HTTP_COPY;
break;
}

if (ngx_str4cmp(parser->buffer, 'M', 'O', 'V', 'E')) {
parser->method = HTTP_MOVE;
break;
}

break;

case 5:
if (ngx_str5cmp(parser->buffer, 'M', 'K', 'C', 'O', 'L')) {
parser->method = HTTP_MKCOL;
break;
}

if (ngx_str5cmp(parser->buffer, 'T', 'R', 'A', 'C', 'E')) {
parser->method = HTTP_TRACE;
break;
}

break;

case 6:
if (ngx_str6cmp(parser->buffer, 'D', 'E', 'L', 'E', 'T', 'E')) {
parser->method = HTTP_DELETE;
break;
}

if (ngx_str6cmp(parser->buffer, 'U', 'N', 'L', 'O', 'C', 'K')) {
parser->method = HTTP_UNLOCK;
break;
}

break;

case 7:
if (ngx_str7_cmp(parser->buffer,
'O', 'P', 'T', 'I', 'O', 'N', 'S', '\0')) {
parser->method = HTTP_OPTIONS;
break;
}

if (ngx_str7_cmp(parser->buffer,
'C', 'O', 'N', 'N', 'E', 'C', 'T', '\0')) {
parser->method = HTTP_CONNECT;
break;
}

break;

case 8:
if (ngx_str8cmp(parser->buffer,
'P', 'R', 'O', 'P', 'F', 'I', 'N', 'D')) {
parser->method = HTTP_PROPFIND;
break;
}

break;

case 9:
if (ngx_str9cmp(parser->buffer,
'P', 'R', 'O', 'P', 'P', 'A', 'T', 'C', 'H')) {
parser->method = HTTP_PROPPATCH;
break;
}
{
if (ch == '\0')
goto error;

break;
}
const char *matcher = method_strings[parser->method];
if (ch == ' ' && matcher[index] == '\0') {
state = s_req_spaces_before_url;
break;
}

if (ch < 'A' || 'Z' < ch) goto error;

if (++index >= HTTP_PARSER_MAX_METHOD_LEN - 1) {
} else if (ch == matcher[index]) {
; // nada
} else if (parser->method == HTTP_CONNECT) {
if (index == 1 && ch == 'H') {
parser->method = HTTP_CHECKOUT;
} else if (index == 2 && ch == 'P') {
parser->method = HTTP_COPY;
}
} else if (parser->method == HTTP_MKCOL) {
if (index == 1 && ch == 'O') {
parser->method = HTTP_MOVE;
} else if (index == 1 && ch == 'E') {
parser->method = HTTP_MERGE;
} else if (index == 2 && ch == 'A') {
parser->method = HTTP_MKACTIVITY;
}
} else if (index == 1 && parser->method == HTTP_POST && ch == 'R') {
parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
} else if (index == 1 && parser->method == HTTP_POST && ch == 'U') {
parser->method = HTTP_PUT;
} else if (index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
parser->method = HTTP_PROPPATCH;
} else {
goto error;
}

parser->buffer[index] = ch;

++index;
break;

}
case s_req_spaces_before_url:
{
if (ch == ' ') break;
Expand Down Expand Up @@ -1069,7 +995,7 @@ size_t http_parser_execute (http_parser *parser,

case s_header_field:
{
c = lowcase[(int)ch];
c = lowcase[(unsigned char)ch];

if (c) {
switch (header_state) {
Expand Down Expand Up @@ -1205,7 +1131,7 @@ size_t http_parser_execute (http_parser *parser,
state = s_header_value;
index = 0;

c = lowcase[(int)ch];
c = lowcase[(unsigned char)ch];

if (!c) {
if (ch == CR) {
Expand Down Expand Up @@ -1266,7 +1192,7 @@ size_t http_parser_execute (http_parser *parser,

case s_header_value:
{
c = lowcase[(int)ch];
c = lowcase[(unsigned char)ch];

if (!c) {
if (ch == CR) {
Expand Down Expand Up @@ -1378,7 +1304,6 @@ size_t http_parser_execute (http_parser *parser,
break;
}

parser->body_read = 0;
nread = 0;

if (parser->flags & F_UPGRADE) parser->upgrade = 1;
Expand Down Expand Up @@ -1439,12 +1364,12 @@ size_t http_parser_execute (http_parser *parser,
}

case s_body_identity:
to_read = MIN(pe - p, (ssize_t)(parser->content_length - parser->body_read));
to_read = MIN(pe - p, (ssize_t)parser->content_length);
if (to_read > 0) {
if (settings->on_body) settings->on_body(parser, p, to_read);
p += to_read - 1;
parser->body_read += to_read;
if (parser->body_read == parser->content_length) {
parser->content_length -= to_read;
if (parser->content_length == 0) {
CALLBACK2(message_complete);
state = NEW_MESSAGE();
}
Expand All @@ -1457,7 +1382,6 @@ size_t http_parser_execute (http_parser *parser,
if (to_read > 0) {
if (settings->on_body) settings->on_body(parser, p, to_read);
p += to_read - 1;
parser->body_read += to_read;
}
break;

Expand Down Expand Up @@ -1598,6 +1522,12 @@ http_should_keep_alive (http_parser *parser)
}


const char * http_method_str (enum http_method m)
{
return method_strings[m];
}


void
http_parser_init (http_parser *parser, enum http_parser_type t)
{
Expand All @@ -1606,4 +1536,3 @@ http_parser_init (http_parser *parser, enum http_parser_type t)
parser->nread = 0;
parser->upgrade = 0;
}

0 comments on commit 8825c74

Please sign in to comment.