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>
|
||||
Corey Richardson <corey@octayn.net>
|
||||
Tóth Tamás <tomika_nospam@freemail.hu>
|
||||
Patrik Stutz <patrik.stutz@gmail.com>
|
||||
Cam Swords <cam.swords@gmail.com>
|
||||
Chris Dickinson <christopher.s.dickinson@gmail.com>
|
||||
Uli Köhler <ukoehler@btronik.de>
|
||||
Charlie Somerville <charlie@charliesomerville.com>
|
||||
Patrik Stutz <patrik.stutz@gmail.com>
|
||||
Fedor Indutny <fedor.indutny@gmail.com>
|
||||
runner <runner.mei@gmail.com>
|
||||
Alexis Campailla <alexis@janeasystems.com>
|
||||
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)
|
||||
|
||||
#define CURRENT_STATE() p_state
|
||||
#define UPDATE_STATE(V) p_state = (V);
|
||||
#define UPDATE_STATE(V) p_state = (enum state) (V);
|
||||
#define RETURN(V) \
|
||||
do { \
|
||||
parser->state = CURRENT_STATE(); \
|
||||
return (V); \
|
||||
} while (0);
|
||||
#define REEXECUTE() \
|
||||
--p; \
|
||||
break;
|
||||
goto reexecute; \
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -637,7 +636,7 @@ size_t http_parser_execute (http_parser *parser,
|
|||
const char *url_mark = 0;
|
||||
const char *body_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. */
|
||||
if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
|
||||
|
@ -697,6 +696,7 @@ size_t http_parser_execute (http_parser *parser,
|
|||
if (PARSING_HEADER(CURRENT_STATE()))
|
||||
COUNT_HEADER_SIZE(1);
|
||||
|
||||
reexecute:
|
||||
switch (CURRENT_STATE()) {
|
||||
|
||||
case s_dead:
|
||||
|
@ -1518,7 +1518,7 @@ size_t http_parser_execute (http_parser *parser,
|
|||
case s_header_value:
|
||||
{
|
||||
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++) {
|
||||
ch = *p;
|
||||
if (ch == CR) {
|
||||
|
@ -1547,8 +1547,8 @@ size_t http_parser_execute (http_parser *parser,
|
|||
|
||||
limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
|
||||
|
||||
p_cr = memchr(p, CR, limit);
|
||||
p_lf = memchr(p, LF, limit);
|
||||
p_cr = (const char*) memchr(p, CR, limit);
|
||||
p_lf = (const char*) memchr(p, LF, limit);
|
||||
if (p_cr != NULL) {
|
||||
if (p_lf != NULL && p_cr >= p_lf)
|
||||
p = p_lf;
|
||||
|
@ -1618,6 +1618,8 @@ size_t http_parser_execute (http_parser *parser,
|
|||
h_state = h_matching_connection_upgrade;
|
||||
} else if (STRICT_TOKEN(c)) {
|
||||
h_state = h_matching_connection_token;
|
||||
} else if (c == ' ' || c == '\t') {
|
||||
/* Skip lws */
|
||||
} else {
|
||||
h_state = h_general;
|
||||
}
|
||||
|
@ -2134,6 +2136,12 @@ http_parser_init (http_parser *parser, enum http_parser_type t)
|
|||
parser->http_errno = HPE_OK;
|
||||
}
|
||||
|
||||
void
|
||||
http_parser_settings_init(http_parser_settings *settings)
|
||||
{
|
||||
memset(settings, 0, sizeof(*settings));
|
||||
}
|
||||
|
||||
const char *
|
||||
http_errno_name(enum http_errno err) {
|
||||
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. */
|
||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||
#define HTTP_PARSER_VERSION_MINOR 3
|
||||
#define HTTP_PARSER_VERSION_PATCH 0
|
||||
#define HTTP_PARSER_VERSION_MINOR 4
|
||||
#define HTTP_PARSER_VERSION_PATCH 2
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
|
||||
|
@ -204,8 +204,8 @@ enum http_errno {
|
|||
struct http_parser {
|
||||
/** PRIVATE **/
|
||||
unsigned int type : 2; /* enum http_parser_type */
|
||||
unsigned int flags : 6; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned int state : 8; /* enum state from http_parser.c */
|
||||
unsigned int flags : 7; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned int state : 7; /* enum 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 */
|
||||
|
||||
|
@ -288,6 +288,11 @@ unsigned long http_parser_version(void);
|
|||
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
|
||||
* `parser->http_errno` on error. */
|
||||
size_t http_parser_execute(http_parser *parser,
|
||||
|
|
|
@ -986,6 +986,55 @@ const struct message requests[] =
|
|||
,.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 */
|
||||
};
|
||||
|
@ -2995,6 +3044,22 @@ test_header_overflow_error (int req)
|
|||
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
|
||||
test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
|
||||
{
|
||||
|
@ -3361,6 +3426,9 @@ main (void)
|
|||
test_parse_url();
|
||||
test_method_str();
|
||||
|
||||
//// NREAD
|
||||
test_header_nread_value();
|
||||
|
||||
//// OVERFLOW CONDITIONS
|
||||
|
||||
test_header_overflow_error(HTTP_REQUEST);
|
||||
|
|
Loading…
Reference in New Issue