commit http-parser for openSUSE:Factory
Hello community, here is the log from the commit of package http-parser for openSUSE:Factory checked in at 2016-04-01 13:01:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/http-parser (Old) and /work/SRC/openSUSE:Factory/.http-parser.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "http-parser" Changes: -------- --- /work/SRC/openSUSE:Factory/http-parser/http-parser.changes 2016-02-07 09:22:27.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.http-parser.new/http-parser.changes 2016-04-01 13:01:11.000000000 +0200 @@ -1,0 +2,6 @@ +Sat Mar 26 12:18:20 UTC 2016 - mpluskal@suse.com + +- Update to 2.6.2 + * No changelog available + +------------------------------------------------------------------- Old: ---- v2.6.0.tar.gz New: ---- v2.6.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ http-parser.spec ++++++ --- /var/tmp/diff_new_pack.5hYEbX/_old 2016-04-01 13:01:12.000000000 +0200 +++ /var/tmp/diff_new_pack.5hYEbX/_new 2016-04-01 13:01:12.000000000 +0200 @@ -1,7 +1,7 @@ # # spec file for package http-parser # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,15 +16,15 @@ # -Name: http-parser %define somajor suse0 -%define libname libhttp-parser-%somajor -Version: 2.6.0 +%define libname libhttp-parser-%{somajor} +Name: http-parser +Version: 2.6.2 Release: 0 Summary: HTTP request/response parser for C License: MIT Group: Development/Libraries/C and C++ -Url: http://github.com/joyent/http-parser +Url: https://github.com/joyent/http-parser Source0: https://github.com/joyent/http-parser/archive/v%{version}.tar.gz Source1: baselibs.conf Patch1: http-parser-gyp-sharedlib.patch @@ -85,12 +85,12 @@ install -pm644 http_parser.h %{buildroot}%{_includedir} #install regular variant -install "out/Release/lib.target/libhttp_parser.so.%somajor" "%buildroot/%_libdir/" -ln -sf "libhttp_parser.so.%somajor" "%buildroot/%_libdir/libhttp_parser.so" +install "out/Release/lib.target/libhttp_parser.so.%{somajor}" "%{buildroot}/%{_libdir}/" +ln -sf "libhttp_parser.so.%{somajor}" "%{buildroot}/%{_libdir}/libhttp_parser.so" #install strict variant -install "out/Release/lib.target/libhttp_parser_strict.so.%somajor" "%buildroot/%_libdir/" -ln -sf "libhttp_parser_strict.so.%somajor" "%buildroot/%_libdir/libhttp_parser_strict.so" +install "out/Release/lib.target/libhttp_parser_strict.so.%{somajor}" "%{buildroot}/%{_libdir}/" +ln -sf "libhttp_parser_strict.so.%{somajor}" "%{buildroot}/%{_libdir}/libhttp_parser_strict.so" %check export LD_LIBRARY_PATH='./out/Release/lib.target' @@ -98,7 +98,6 @@ ./out/Release/test-strict %post -n %{libname} -p /sbin/ldconfig - %postun -n %{libname} -p /sbin/ldconfig %files -n %{libname} ++++++ http-parser-gyp-sharedlib.patch ++++++ --- /var/tmp/diff_new_pack.5hYEbX/_old 2016-04-01 13:01:12.000000000 +0200 +++ /var/tmp/diff_new_pack.5hYEbX/_new 2016-04-01 13:01:12.000000000 +0200 @@ -12,10 +12,10 @@ http_parser.gyp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) -Index: http-parser-2.5.0/http_parser.gyp +Index: http-parser-2.6.2/http_parser.gyp =================================================================== ---- http-parser-2.5.0.orig/http_parser.gyp -+++ http-parser-2.5.0/http_parser.gyp +--- http-parser-2.6.2.orig/http_parser.gyp ++++ http-parser-2.6.2/http_parser.gyp @@ -12,7 +12,7 @@ # RuntimeLibrary MUST MATCH across the entire project 'Debug': { ++++++ v2.6.0.tar.gz -> v2.6.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/http-parser-2.6.0/Makefile new/http-parser-2.6.2/Makefile --- old/http-parser-2.6.0/Makefile 2015-10-29 05:47:12.000000000 +0100 +++ new/http-parser-2.6.2/Makefile 2016-03-04 21:27:05.000000000 +0100 @@ -22,14 +22,14 @@ HELPER ?= BINEXT ?= ifeq (darwin,$(PLATFORM)) -SONAME ?= libhttp_parser.2.6.0.dylib +SONAME ?= libhttp_parser.2.6.2.dylib SOEXT ?= dylib else ifeq (wine,$(PLATFORM)) CC = winegcc BINEXT = .exe.so HELPER = wine else -SONAME ?= libhttp_parser.so.2.6.0 +SONAME ?= libhttp_parser.so.2.6.2 SOEXT ?= so endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/http-parser-2.6.0/README.md new/http-parser-2.6.2/README.md --- old/http-parser-2.6.0/README.md 2015-10-29 05:47:12.000000000 +0100 +++ new/http-parser-2.6.2/README.md 2016-03-04 21:27:05.000000000 +0100 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/http-parser-2.6.0/http_parser.c new/http-parser-2.6.2/http_parser.c --- old/http-parser-2.6.0/http_parser.c 2015-10-29 05:47:12.000000000 +0100 +++ new/http-parser-2.6.2/http_parser.c 2016-03-04 21:27:05.000000000 +0100 @@ -123,7 +123,7 @@ 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) @@ -435,6 +435,12 @@ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') #endif +/** + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + **/ +#define IS_HEADER_CHAR(ch) \ + (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) @@ -639,6 +645,7 @@ const char *body_mark = 0; 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) { @@ -1000,89 +1007,40 @@ 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; @@ -1408,7 +1366,12 @@ || c != CONTENT_LENGTH[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { + if (parser->flags & F_CONTENTLENGTH) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } parser->header_state = h_content_length; + parser->flags |= F_CONTENTLENGTH; } break; @@ -1560,6 +1523,11 @@ REEXECUTE(); } + if (!lenient && !IS_HEADER_CHAR(ch)) { + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + c = LOWER(ch); switch (h_state) { @@ -1727,7 +1695,10 @@ case s_header_almost_done: { - STRICT_CHECK(ch != LF); + if (UNLIKELY(ch != LF)) { + SET_ERRNO(HPE_LF_EXPECTED); + goto error; + } UPDATE_STATE(s_header_value_lws); break; @@ -1811,6 +1782,14 @@ REEXECUTE(); } + /* Cannot use chunked encoding and a content-length header together + per the HTTP specification. */ + if ((parser->flags & F_CHUNKED) && + (parser->flags & F_CONTENTLENGTH)) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + UPDATE_STATE(s_headers_done); /* Set this here so that on_headers_complete() callbacks can see it */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/http-parser-2.6.0/http_parser.h new/http-parser-2.6.2/http_parser.h --- old/http-parser-2.6.0/http_parser.h 2015-10-29 05:47:12.000000000 +0100 +++ new/http-parser-2.6.2/http_parser.h 2016-03-04 21:27:05.000000000 +0100 @@ -27,7 +27,7 @@ /* Also update SONAME in the Makefile whenever you change these. */ #define HTTP_PARSER_VERSION_MAJOR 2 #define HTTP_PARSER_VERSION_MINOR 6 -#define HTTP_PARSER_VERSION_PATCH 0 +#define HTTP_PARSER_VERSION_PATCH 2 #include <sys/types.h> #if defined(_WIN32) && !defined(__MINGW32__) && \ @@ -148,6 +148,7 @@ , F_TRAILING = 1 << 4 , F_UPGRADE = 1 << 5 , F_SKIPBODY = 1 << 6 + , F_CONTENTLENGTH = 1 << 7 }; @@ -190,6 +191,8 @@ XX(INVALID_HEADER_TOKEN, "invalid character in header") \ XX(INVALID_CONTENT_LENGTH, \ "invalid character in content-length header") \ + XX(UNEXPECTED_CONTENT_LENGTH, \ + "unexpected content-length header") \ XX(INVALID_CHUNK_SIZE, \ "invalid character in chunk size header") \ XX(INVALID_CONSTANT, "invalid constant string") \ @@ -214,10 +217,11 @@ struct http_parser { /** PRIVATE **/ unsigned int type : 2; /* enum http_parser_type */ - unsigned int flags : 7; /* F_* values from 'flags' enum; semi-public */ + unsigned int flags : 8; /* 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 */ + unsigned int header_state : 7; /* enum header_state from http_parser.c */ + unsigned int index : 7; /* index into current matcher */ + unsigned int lenient_http_headers : 1; uint32_t nread; /* # bytes read in various scenarios */ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/http-parser-2.6.0/test.c new/http-parser-2.6.2/test.c --- old/http-parser-2.6.0/test.c 2015-10-29 05:47:12.000000000 +0100 +++ new/http-parser-2.6.2/test.c 2016-03-04 21:27:05.000000000 +0100 @@ -2444,7 +2444,7 @@ va_list ap; size_t i; size_t off = 0; - + va_start(ap, nmsgs); for (i = 0; i < nmsgs; i++) { @@ -3271,6 +3271,155 @@ } void +test_invalid_header_content (int req, const char* str) +{ + http_parser parser; + http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); + size_t parsed; + const char *buf; + buf = req ? + "GET / HTTP/1.1\r\n" : + "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); + return; + } + + fprintf(stderr, + "\n*** Error expected but none in invalid header content test ***\n"); + abort(); +} + +void +test_invalid_header_field_content_error (int req) +{ + test_invalid_header_content(req, "Foo: F\01ailure"); + test_invalid_header_content(req, "Foo: B\02ar"); +} + +void +test_invalid_header_field (int req, const char* str) +{ + http_parser parser; + http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); + size_t parsed; + const char *buf; + buf = req ? + "GET / HTTP/1.1\r\n" : + "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); + return; + } + + fprintf(stderr, + "\n*** Error expected but none in invalid header token test ***\n"); + abort(); +} + +void +test_invalid_header_field_token_error (int req) +{ + test_invalid_header_field(req, "Fo@: Failure"); + test_invalid_header_field(req, "Foo\01\test: Bar"); +} + +void +test_double_content_length_error (int req) +{ + http_parser parser; + http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); + size_t parsed; + const char *buf; + buf = req ? + "GET / HTTP/1.1\r\n" : + "HTTP/1.1 200 OK\r\n"; + parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); + assert(parsed == strlen(buf)); + + buf = "Content-Length: 0\r\nContent-Length: 1\r\n\r\n"; + size_t buflen = strlen(buf); + + parsed = http_parser_execute(&parser, &settings_null, buf, buflen); + if (parsed != buflen) { + assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); + return; + } + + fprintf(stderr, + "\n*** Error expected but none in double content-length test ***\n"); + abort(); +} + +void +test_chunked_content_length_error (int req) +{ + http_parser parser; + http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); + size_t parsed; + const char *buf; + buf = req ? + "GET / HTTP/1.1\r\n" : + "HTTP/1.1 200 OK\r\n"; + parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); + assert(parsed == strlen(buf)); + + buf = "Transfer-Encoding: chunked\r\nContent-Length: 1\r\n\r\n"; + size_t buflen = strlen(buf); + + parsed = http_parser_execute(&parser, &settings_null, buf, buflen); + if (parsed != buflen) { + assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); + return; + } + + fprintf(stderr, + "\n*** Error expected but none in chunked content-length test ***\n"); + abort(); +} + +void +test_header_cr_no_lf_error (int req) +{ + http_parser parser; + http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); + size_t parsed; + const char *buf; + buf = req ? + "GET / HTTP/1.1\r\n" : + "HTTP/1.1 200 OK\r\n"; + parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); + assert(parsed == strlen(buf)); + + buf = "Foo: 1\rBar: 1\r\n\r\n"; + size_t buflen = strlen(buf); + + parsed = http_parser_execute(&parser, &settings_null, buf, buflen); + if (parsed != buflen) { + assert(HTTP_PARSER_ERRNO(&parser) == HPE_LF_EXPECTED); + return; + } + + fprintf(stderr, + "\n*** Error expected but none in header whitespace test ***\n"); + abort(); +} + +void test_header_overflow_error (int req) { http_parser parser; @@ -3696,6 +3845,18 @@ test_header_content_length_overflow_error(); test_chunk_content_length_overflow_error(); + //// HEADER FIELD CONDITIONS + test_double_content_length_error(HTTP_REQUEST); + test_chunked_content_length_error(HTTP_REQUEST); + test_header_cr_no_lf_error(HTTP_REQUEST); + test_invalid_header_field_token_error(HTTP_REQUEST); + test_invalid_header_field_content_error(HTTP_REQUEST); + test_double_content_length_error(HTTP_RESPONSE); + test_chunked_content_length_error(HTTP_RESPONSE); + test_header_cr_no_lf_error(HTTP_RESPONSE); + test_invalid_header_field_token_error(HTTP_RESPONSE); + test_invalid_header_field_content_error(HTTP_RESPONSE); + //// RESPONSES for (i = 0; i < response_count; i++) { @@ -3772,6 +3933,11 @@ 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"
participants (1)
-
root@hilbert.suse.de