From cf0b3dc3f003013c943928131cef553a88f811a7 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 8 Mar 2016 07:51:54 -0800 Subject: [PATCH] deps: sync deps/http_parser with nodejs/http_parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The upstream and dep were slightly out of sync due to the way the recent security update had to be done. This brings the two back into sync. This update includes a couple of fixed tests and a performance related semver-patch update to the http method parsing. PR-URL: https://github.com/nodejs/node/pull/5600 Reviewed-By: Fedor Indutny Reviewed-By: Johan Bergström --- deps/http_parser/README.md | 2 +- deps/http_parser/http_parser.c | 115 ++++++++++----------------------- deps/http_parser/test.c | 17 +++-- 3 files changed, 45 insertions(+), 89 deletions(-) diff --git a/deps/http_parser/README.md b/deps/http_parser/README.md index abee9469338424..eedd7f8c9a4d0f 100644 --- a/deps/http_parser/README.md +++ b/deps/http_parser/README.md @@ -1,7 +1,7 @@ HTTP Parser =========== -[![Build Status](https://travis-ci.org/joyent/http-parser.png?branch=master)](https://travis-ci.org/joyent/http-parser) +[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) This is a parser for HTTP messages written in C. It parses both requests and responses. The parser is designed to be used in performance HTTP diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c index 852bed042e9b21..d51a2e7bcdf30a 100644 --- a/deps/http_parser/http_parser.c +++ b/deps/http_parser/http_parser.c @@ -123,7 +123,7 @@ do { \ FOR##_mark = NULL; \ } \ } while (0) - + /* Run the data callback FOR and consume the current byte */ #define CALLBACK_DATA(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) @@ -646,7 +646,7 @@ size_t http_parser_execute (http_parser *parser, const char *status_mark = 0; enum state p_state = (enum state) parser->state; const unsigned int lenient = parser->lenient_http_headers; - + /* We're in an error state. Don't bother doing anything. */ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { return 0; @@ -1007,89 +1007,40 @@ size_t http_parser_execute (http_parser *parser, UPDATE_STATE(s_req_spaces_before_url); } else if (ch == matcher[parser->index]) { ; /* nada */ - } else if (parser->method == HTTP_CONNECT) { - if (parser->index == 1 && ch == 'H') { - parser->method = HTTP_CHECKOUT; - } else if (parser->index == 2 && ch == 'P') { - parser->method = HTTP_COPY; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_MKCOL) { - if (parser->index == 1 && ch == 'O') { - parser->method = HTTP_MOVE; - } else if (parser->index == 1 && ch == 'E') { - parser->method = HTTP_MERGE; - } else if (parser->index == 1 && ch == '-') { - parser->method = HTTP_MSEARCH; - } else if (parser->index == 2 && ch == 'A') { - parser->method = HTTP_MKACTIVITY; - } else if (parser->index == 3 && ch == 'A') { - parser->method = HTTP_MKCALENDAR; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_SUBSCRIBE) { - if (parser->index == 1 && ch == 'E') { - parser->method = HTTP_SEARCH; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_REPORT) { - if (parser->index == 2 && ch == 'B') { - parser->method = HTTP_REBIND; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->index == 1) { - if (parser->method == HTTP_POST) { - if (ch == 'R') { - parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */ - } else if (ch == 'U') { - parser->method = HTTP_PUT; /* or HTTP_PURGE */ - } else if (ch == 'A') { - parser->method = HTTP_PATCH; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_LOCK) { - if (ch == 'I') { - parser->method = HTTP_LINK; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } - } else if (parser->index == 2) { - if (parser->method == HTTP_PUT) { - if (ch == 'R') { - parser->method = HTTP_PURGE; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (parser->method == HTTP_UNLOCK) { - if (ch == 'S') { - parser->method = HTTP_UNSUBSCRIBE; - } else if(ch == 'B') { - parser->method = HTTP_UNBIND; - } else { + } else if (IS_ALPHA(ch)) { + + switch (parser->method << 16 | parser->index << 8 | ch) { +#define XX(meth, pos, ch, new_meth) \ + case (HTTP_##meth << 16 | pos << 8 | ch): \ + parser->method = HTTP_##new_meth; break; + + XX(POST, 1, 'U', PUT) + XX(POST, 1, 'A', PATCH) + XX(CONNECT, 1, 'H', CHECKOUT) + XX(CONNECT, 2, 'P', COPY) + XX(MKCOL, 1, 'O', MOVE) + XX(MKCOL, 1, 'E', MERGE) + XX(MKCOL, 2, 'A', MKACTIVITY) + XX(MKCOL, 3, 'A', MKCALENDAR) + XX(SUBSCRIBE, 1, 'E', SEARCH) + XX(REPORT, 2, 'B', REBIND) + XX(POST, 1, 'R', PROPFIND) + XX(PROPFIND, 4, 'P', PROPPATCH) + XX(PUT, 2, 'R', PURGE) + XX(LOCK, 1, 'I', LINK) + XX(UNLOCK, 2, 'S', UNSUBSCRIBE) + XX(UNLOCK, 2, 'B', UNBIND) + XX(UNLOCK, 3, 'I', UNLINK) +#undef XX + + default: SET_ERRNO(HPE_INVALID_METHOD); goto error; - } - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; } - } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') { - parser->method = HTTP_PROPPATCH; - } else if (parser->index == 3 && parser->method == HTTP_UNLOCK && ch == 'I') { - parser->method = HTTP_UNLINK; + } else if (ch == '-' && + parser->index == 1 && + parser->method == HTTP_MKCOL) { + parser->method = HTTP_MSEARCH; } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c index 26092411c7e16a..7b01dc346b63d9 100644 --- a/deps/http_parser/test.c +++ b/deps/http_parser/test.c @@ -2444,7 +2444,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) { va_list ap; size_t i; size_t off = 0; - + va_start(ap, nmsgs); for (i = 0; i < nmsgs; i++) { @@ -3282,10 +3282,10 @@ test_invalid_header_content (int req, const char* str) "HTTP/1.1 200 OK\r\n"; parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); assert(parsed == strlen(buf)); - + buf = str; size_t buflen = strlen(buf); - + parsed = http_parser_execute(&parser, &settings_null, buf, buflen); if (parsed != buflen) { assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); @@ -3316,10 +3316,10 @@ test_invalid_header_field (int req, const char* str) "HTTP/1.1 200 OK\r\n"; parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); assert(parsed == strlen(buf)); - + buf = str; size_t buflen = strlen(buf); - + parsed = http_parser_execute(&parser, &settings_null, buf, buflen); if (parsed != buflen) { assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); @@ -3383,7 +3383,7 @@ test_chunked_content_length_error (int req) parsed = http_parser_execute(&parser, &settings_null, buf, buflen); if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_CHUNKED_WITH_CONTENT_LENGTH); + assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); return; } @@ -3933,6 +3933,11 @@ main (void) test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION); + // Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js + test_simple("GET / HTTP/1.1\r\n" + "Test: Düsseldorf\r\n", + HPE_OK); + // Well-formed but incomplete test_simple("GET / HTTP/1.1\r\n" "Content-Type: text/plain\r\n"