Update http-parser
This commit is contained in:
parent
4424cf5b65
commit
83d9ee1fd1
|
@ -39,12 +39,25 @@ BogDan Vatra <bogdan@kde.org>
|
||||||
Peter Faiman <peter@thepicard.org>
|
Peter Faiman <peter@thepicard.org>
|
||||||
Corey Richardson <corey@octayn.net>
|
Corey Richardson <corey@octayn.net>
|
||||||
Tóth Tamás <tomika_nospam@freemail.hu>
|
Tóth Tamás <tomika_nospam@freemail.hu>
|
||||||
Patrik Stutz <patrik.stutz@gmail.com>
|
|
||||||
Cam Swords <cam.swords@gmail.com>
|
Cam Swords <cam.swords@gmail.com>
|
||||||
Chris Dickinson <christopher.s.dickinson@gmail.com>
|
Chris Dickinson <christopher.s.dickinson@gmail.com>
|
||||||
Uli Köhler <ukoehler@btronik.de>
|
Uli Köhler <ukoehler@btronik.de>
|
||||||
Charlie Somerville <charlie@charliesomerville.com>
|
Charlie Somerville <charlie@charliesomerville.com>
|
||||||
|
Patrik Stutz <patrik.stutz@gmail.com>
|
||||||
Fedor Indutny <fedor.indutny@gmail.com>
|
Fedor Indutny <fedor.indutny@gmail.com>
|
||||||
runner <runner.mei@gmail.com>
|
runner <runner.mei@gmail.com>
|
||||||
Alexis Campailla <alexis@janeasystems.com>
|
Alexis Campailla <alexis@janeasystems.com>
|
||||||
David Wragg <david@wragg.org>
|
David Wragg <david@wragg.org>
|
||||||
|
Vinnie Falco <vinnie.falco@gmail.com>
|
||||||
|
Alex Butum <alexbutum@linux.com>
|
||||||
|
Rex Feng <rexfeng@gmail.com>
|
||||||
|
Alex Kocharin <alex@kocharin.ru>
|
||||||
|
Mark Koopman <markmontymark@yahoo.com>
|
||||||
|
Helge Heß <me@helgehess.eu>
|
||||||
|
Alexis La Goutte <alexis.lagoutte@gmail.com>
|
||||||
|
George Miroshnykov <george.miroshnykov@gmail.com>
|
||||||
|
Maciej Małecki <me@mmalecki.com>
|
||||||
|
Marc O'Morain <github.com@marcomorain.com>
|
||||||
|
Jeff Pinner <jpinner@twitter.com>
|
||||||
|
Timothy J Fontaine <tjfontaine@gmail.com>
|
||||||
|
Akagi201 <akagi201@gmail.com>
|
||||||
|
|
|
@ -57,15 +57,14 @@ do { \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define CURRENT_STATE() p_state
|
#define CURRENT_STATE() p_state
|
||||||
#define UPDATE_STATE(V) p_state = (V);
|
#define UPDATE_STATE(V) p_state = (enum state) (V);
|
||||||
#define RETURN(V) \
|
#define RETURN(V) \
|
||||||
do { \
|
do { \
|
||||||
parser->state = CURRENT_STATE(); \
|
parser->state = CURRENT_STATE(); \
|
||||||
return (V); \
|
return (V); \
|
||||||
} while (0);
|
} while (0);
|
||||||
#define REEXECUTE() \
|
#define REEXECUTE() \
|
||||||
--p; \
|
goto reexecute; \
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -637,7 +636,7 @@ size_t http_parser_execute (http_parser *parser,
|
||||||
const char *url_mark = 0;
|
const char *url_mark = 0;
|
||||||
const char *body_mark = 0;
|
const char *body_mark = 0;
|
||||||
const char *status_mark = 0;
|
const char *status_mark = 0;
|
||||||
enum state p_state = parser->state;
|
enum state p_state = (enum state) parser->state;
|
||||||
|
|
||||||
/* We're in an error state. Don't bother doing anything. */
|
/* We're in an error state. Don't bother doing anything. */
|
||||||
if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
|
if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
|
||||||
|
@ -697,6 +696,7 @@ size_t http_parser_execute (http_parser *parser,
|
||||||
if (PARSING_HEADER(CURRENT_STATE()))
|
if (PARSING_HEADER(CURRENT_STATE()))
|
||||||
COUNT_HEADER_SIZE(1);
|
COUNT_HEADER_SIZE(1);
|
||||||
|
|
||||||
|
reexecute:
|
||||||
switch (CURRENT_STATE()) {
|
switch (CURRENT_STATE()) {
|
||||||
|
|
||||||
case s_dead:
|
case s_dead:
|
||||||
|
@ -1518,7 +1518,7 @@ size_t http_parser_execute (http_parser *parser,
|
||||||
case s_header_value:
|
case s_header_value:
|
||||||
{
|
{
|
||||||
const char* start = p;
|
const char* start = p;
|
||||||
enum header_states h_state = parser->header_state;
|
enum header_states h_state = (enum header_states) parser->header_state;
|
||||||
for (; p != data + len; p++) {
|
for (; p != data + len; p++) {
|
||||||
ch = *p;
|
ch = *p;
|
||||||
if (ch == CR) {
|
if (ch == CR) {
|
||||||
|
@ -1547,8 +1547,8 @@ size_t http_parser_execute (http_parser *parser,
|
||||||
|
|
||||||
limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
|
limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
|
||||||
|
|
||||||
p_cr = memchr(p, CR, limit);
|
p_cr = (const char*) memchr(p, CR, limit);
|
||||||
p_lf = memchr(p, LF, limit);
|
p_lf = (const char*) memchr(p, LF, limit);
|
||||||
if (p_cr != NULL) {
|
if (p_cr != NULL) {
|
||||||
if (p_lf != NULL && p_cr >= p_lf)
|
if (p_lf != NULL && p_cr >= p_lf)
|
||||||
p = p_lf;
|
p = p_lf;
|
||||||
|
@ -1618,6 +1618,8 @@ size_t http_parser_execute (http_parser *parser,
|
||||||
h_state = h_matching_connection_upgrade;
|
h_state = h_matching_connection_upgrade;
|
||||||
} else if (STRICT_TOKEN(c)) {
|
} else if (STRICT_TOKEN(c)) {
|
||||||
h_state = h_matching_connection_token;
|
h_state = h_matching_connection_token;
|
||||||
|
} else if (c == ' ' || c == '\t') {
|
||||||
|
/* Skip lws */
|
||||||
} else {
|
} else {
|
||||||
h_state = h_general;
|
h_state = h_general;
|
||||||
}
|
}
|
||||||
|
@ -2134,6 +2136,12 @@ http_parser_init (http_parser *parser, enum http_parser_type t)
|
||||||
parser->http_errno = HPE_OK;
|
parser->http_errno = HPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
http_parser_settings_init(http_parser_settings *settings)
|
||||||
|
{
|
||||||
|
memset(settings, 0, sizeof(*settings));
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
http_errno_name(enum http_errno err) {
|
http_errno_name(enum http_errno err) {
|
||||||
assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));
|
assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));
|
||||||
|
|
|
@ -26,8 +26,8 @@ extern "C" {
|
||||||
|
|
||||||
/* Also update SONAME in the Makefile whenever you change these. */
|
/* Also update SONAME in the Makefile whenever you change these. */
|
||||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||||
#define HTTP_PARSER_VERSION_MINOR 3
|
#define HTTP_PARSER_VERSION_MINOR 4
|
||||||
#define HTTP_PARSER_VERSION_PATCH 0
|
#define HTTP_PARSER_VERSION_PATCH 2
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
|
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
|
||||||
|
@ -204,8 +204,8 @@ enum http_errno {
|
||||||
struct http_parser {
|
struct http_parser {
|
||||||
/** PRIVATE **/
|
/** PRIVATE **/
|
||||||
unsigned int type : 2; /* enum http_parser_type */
|
unsigned int type : 2; /* enum http_parser_type */
|
||||||
unsigned int flags : 6; /* F_* values from 'flags' enum; semi-public */
|
unsigned int flags : 7; /* F_* values from 'flags' enum; semi-public */
|
||||||
unsigned int state : 8; /* enum state from http_parser.c */
|
unsigned int state : 7; /* enum state from http_parser.c */
|
||||||
unsigned int header_state : 8; /* enum header_state from http_parser.c */
|
unsigned int header_state : 8; /* enum header_state from http_parser.c */
|
||||||
unsigned int index : 8; /* index into current matcher */
|
unsigned int index : 8; /* index into current matcher */
|
||||||
|
|
||||||
|
@ -288,6 +288,11 @@ unsigned long http_parser_version(void);
|
||||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize http_parser_settings members to 0
|
||||||
|
*/
|
||||||
|
void http_parser_settings_init(http_parser_settings *settings);
|
||||||
|
|
||||||
|
|
||||||
/* Executes the parser. Returns number of parsed bytes. Sets
|
/* Executes the parser. Returns number of parsed bytes. Sets
|
||||||
* `parser->http_errno` on error. */
|
* `parser->http_errno` on error. */
|
||||||
size_t http_parser_execute(http_parser *parser,
|
size_t http_parser_execute(http_parser *parser,
|
||||||
|
|
|
@ -986,6 +986,55 @@ const struct message requests[] =
|
||||||
,.body= ""
|
,.body= ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CONNECTION_MULTI_LWS 36
|
||||||
|
, {.name = "multiple connection header values with folding and lws"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "GET /demo HTTP/1.1\r\n"
|
||||||
|
"Connection: keep-alive, upgrade\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"Hot diggity dogg"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_GET
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.request_path= "/demo"
|
||||||
|
,.request_url= "/demo"
|
||||||
|
,.num_headers= 2
|
||||||
|
,.upgrade="Hot diggity dogg"
|
||||||
|
,.headers= { { "Connection", "keep-alive, upgrade" }
|
||||||
|
, { "Upgrade", "WebSocket" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CONNECTION_MULTI_LWS_CRLF 37
|
||||||
|
, {.name = "multiple connection header values with folding and lws"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "GET /demo HTTP/1.1\r\n"
|
||||||
|
"Connection: keep-alive, \r\n upgrade\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"Hot diggity dogg"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_GET
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.request_path= "/demo"
|
||||||
|
,.request_url= "/demo"
|
||||||
|
,.num_headers= 2
|
||||||
|
,.upgrade="Hot diggity dogg"
|
||||||
|
,.headers= { { "Connection", "keep-alive, upgrade" }
|
||||||
|
, { "Upgrade", "WebSocket" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
, {.name= NULL } /* sentinel */
|
, {.name= NULL } /* sentinel */
|
||||||
};
|
};
|
||||||
|
@ -2995,6 +3044,22 @@ test_header_overflow_error (int req)
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
test_header_nread_value ()
|
||||||
|
{
|
||||||
|
http_parser parser;
|
||||||
|
http_parser_init(&parser, HTTP_REQUEST);
|
||||||
|
size_t parsed;
|
||||||
|
const char *buf;
|
||||||
|
buf = "GET / HTTP/1.1\r\nheader: value\nhdr: value\r\n";
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
||||||
|
assert(parsed == strlen(buf));
|
||||||
|
|
||||||
|
assert(parser.nread == strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
|
test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
|
||||||
{
|
{
|
||||||
|
@ -3361,6 +3426,9 @@ main (void)
|
||||||
test_parse_url();
|
test_parse_url();
|
||||||
test_method_str();
|
test_method_str();
|
||||||
|
|
||||||
|
//// NREAD
|
||||||
|
test_header_nread_value();
|
||||||
|
|
||||||
//// OVERFLOW CONDITIONS
|
//// OVERFLOW CONDITIONS
|
||||||
|
|
||||||
test_header_overflow_error(HTTP_REQUEST);
|
test_header_overflow_error(HTTP_REQUEST);
|
||||||
|
|
Loading…
Reference in New Issue