From fcdfd299397e3853753f35dafaa549c9be819eaf Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Mon, 12 Feb 2018 18:05:16 +0200 Subject: [PATCH] Sync http parser with upstream --- vendor/http-parser/Makefile | 4 +-- vendor/http-parser/http_parser.c | 31 ++++++++++++++++------ vendor/http-parser/http_parser.h | 6 +++-- vendor/http-parser/test.c | 45 ++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 12 deletions(-) diff --git a/vendor/http-parser/Makefile b/vendor/http-parser/Makefile index 8b7b9bb0f70..6cf63bd35ea 100644 --- a/vendor/http-parser/Makefile +++ b/vendor/http-parser/Makefile @@ -23,8 +23,8 @@ HELPER ?= BINEXT ?= SOLIBNAME = libhttp_parser SOMAJOR = 2 -SOMINOR = 7 -SOREV = 1 +SOMINOR = 8 +SOREV = 0 ifeq (darwin,$(PLATFORM)) SOEXT ?= dylib SONAME ?= $(SOLIBNAME).$(SOMAJOR).$(SOMINOR).$(SOEXT) diff --git a/vendor/http-parser/http_parser.c b/vendor/http-parser/http_parser.c index 8d851245cb9..5b5657b02c5 100644 --- a/vendor/http-parser/http_parser.c +++ b/vendor/http-parser/http_parser.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -943,7 +942,7 @@ size_t http_parser_execute (http_parser *parser, /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ break; case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; - case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; + case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH, SOURCE */ break; case 'T': parser->method = HTTP_TRACE; break; case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; default: @@ -989,6 +988,7 @@ size_t http_parser_execute (http_parser *parser, XX(MKCOL, 2, 'A', MKACTIVITY) XX(MKCOL, 3, 'A', MKCALENDAR) XX(SUBSCRIBE, 1, 'E', SEARCH) + XX(SUBSCRIBE, 1, 'O', SOURCE) XX(REPORT, 2, 'B', REBIND) XX(PROPFIND, 4, 'P', PROPPATCH) XX(LOCK, 1, 'I', LINK) @@ -2367,12 +2367,27 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect, } if (u->field_set & (1 << UF_PORT)) { - /* Don't bother with endp; we've already validated the string */ - unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); - - /* Ports have a max value of 2^16 */ - if (v > 0xffff) { - return 1; + uint16_t off; + uint16_t len; + const char* p; + const char* end; + unsigned long v; + + off = u->field_data[UF_PORT].off; + len = u->field_data[UF_PORT].len; + end = buf + off + len; + + /* NOTE: The characters are already validated and are in the [0-9] range */ + assert(off + len <= buflen && "Port number overflow"); + v = 0; + for (p = buf + off; p < end; p++) { + v *= 10; + v += *p - '0'; + + /* Ports have a max value of 2^16 */ + if (v > 0xffff) { + return 1; + } } u->port = (uint16_t) v; diff --git a/vendor/http-parser/http_parser.h b/vendor/http-parser/http_parser.h index fd2a564148b..1fbf30e2b47 100644 --- a/vendor/http-parser/http_parser.h +++ b/vendor/http-parser/http_parser.h @@ -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 7 -#define HTTP_PARSER_VERSION_PATCH 1 +#define HTTP_PARSER_VERSION_MINOR 8 +#define HTTP_PARSER_VERSION_PATCH 0 #include #if defined(_WIN32) && !defined(__MINGW32__) && \ @@ -201,6 +201,8 @@ enum http_status /* RFC-2068, section 19.6.1.2 */ \ XX(31, LINK, LINK) \ XX(32, UNLINK, UNLINK) \ + /* icecast */ \ + XX(33, SOURCE, SOURCE) \ enum http_method { diff --git a/vendor/http-parser/test.c b/vendor/http-parser/test.c index 193004e2cef..bc4e664f525 100644 --- a/vendor/http-parser/test.c +++ b/vendor/http-parser/test.c @@ -1154,6 +1154,26 @@ const struct message requests[] = ,.body= "" } +#define SOURCE_REQUEST 42 +, {.name = "source request" + ,.type= HTTP_REQUEST + ,.raw= "SOURCE /music/sweet/music HTTP/1.1\r\n" + "Host: example.com\r\n" + "\r\n" + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.method= HTTP_SOURCE + ,.request_path= "/music/sweet/music" + ,.request_url= "/music/sweet/music" + ,.query_string= "" + ,.fragment= "" + ,.num_headers= 1 + ,.headers= { { "Host", "example.com" } } + ,.body= "" + } + , {.name= NULL } /* sentinel */ }; @@ -3664,6 +3684,30 @@ test_header_cr_no_lf_error (int req) abort(); } +void +test_no_overflow_parse_url (void) +{ + int rv; + struct http_parser_url u; + + http_parser_url_init(&u); + rv = http_parser_parse_url("http://example.com:8001", 22, 0, &u); + + if (rv != 0) { + fprintf(stderr, + "\n*** test_no_overflow_parse_url invalid return value=%d\n", + rv); + abort(); + } + + if (u.port != 800) { + fprintf(stderr, + "\n*** test_no_overflow_parse_url invalid port number=%d\n", + u.port); + abort(); + } +} + void test_header_overflow_error (int req) { @@ -4099,6 +4143,7 @@ main (void) test_header_nread_value(); //// OVERFLOW CONDITIONS + test_no_overflow_parse_url(); test_header_overflow_error(HTTP_REQUEST); test_no_overflow_long_body(HTTP_REQUEST, 1000);