From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id B1AFB26749 for ; Fri, 15 Jun 2018 10:24:23 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id xyEua0sfFuxN for ; Fri, 15 Jun 2018 10:24:23 -0400 (EDT) Received: from smtp50.i.mail.ru (smtp50.i.mail.ru [94.100.177.110]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 5FC5B210C0 for ; Fri, 15 Jun 2018 10:24:23 -0400 (EDT) From: Ilya Markov Subject: [tarantool-patches] [http.client 1/2] http: Remove parsed status line from headers Date: Fri, 15 Jun 2018 17:24:10 +0300 Message-Id: <02e9c328f4c895dec7655e91ab62004988ff0575.1529072604.git.imarkov@tarantool.org> In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: georgy@tarantool.org Cc: tarantool-patches@freelists.org Bug: Header parser validates http status line and besides saving http status, saves valid characters to header name, which is wrong. Fix this with skipping status line after validation without saving it as a header. In scope of #3451 --- src/http_parser.c | 30 +++++++++++++++++++++++++++++- src/http_parser.h | 1 + src/lua/httpc.c | 3 +-- test/app-tap/http_client.test.lua | 3 ++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/http_parser.c b/src/http_parser.c index 7166903..64f20e5 100644 --- a/src/http_parser.c +++ b/src/http_parser.c @@ -220,6 +220,8 @@ http_parse_header_line(struct http_parser *parser, char **bufp, enum { sw_start = 0, + skip_status_line, + skipped_status_line_almost_done, sw_name, sw_space_before_value, sw_value, @@ -271,6 +273,25 @@ http_parse_header_line(struct http_parser *parser, char **bufp, break; } break; + case skip_status_line: + switch (ch) { + case LF: + goto skipped_status; + case CR: + state = skipped_status_line_almost_done; + default: + break; + } + break; + case skipped_status_line_almost_done: + switch (ch) { + case LF: + goto skipped_status; + case CR: + break; + default: + return HTTP_PARSE_INVALID; + } /* http_header name */ case sw_name: c = lowcase[ch]; @@ -304,8 +325,11 @@ http_parse_header_line(struct http_parser *parser, char **bufp, if (rc == HTTP_PARSE_INVALID) { parser->http_minor = -1; parser->http_major = -1; + state = sw_start; + } else { + /* Skip it till end of line. */ + state = skip_status_line; } - state = sw_start; break; } if (ch == '\0') @@ -389,6 +413,10 @@ http_parse_header_line(struct http_parser *parser, char **bufp, } } +skipped_status: + *bufp = p + 1; + return HTTP_PARSE_CONTINUE; + done: *bufp = p + 1; return HTTP_PARSE_OK; diff --git a/src/http_parser.h b/src/http_parser.h index 5e20f53..c4d59a9 100644 --- a/src/http_parser.h +++ b/src/http_parser.h @@ -36,6 +36,7 @@ enum { HTTP_PARSE_OK, + HTTP_PARSE_CONTINUE, HTTP_PARSE_DONE, HTTP_PARSE_INVALID }; diff --git a/src/lua/httpc.c b/src/lua/httpc.c index 45abb98..0fe27d4 100644 --- a/src/lua/httpc.c +++ b/src/lua/httpc.c @@ -69,13 +69,12 @@ parse_headers(lua_State *L, char *buffer, size_t len) lua_newtable(L); while (true) { int rc = http_parse_header_line(&parser, &buffer, end_buf); - if (rc == HTTP_PARSE_INVALID) { + if (rc == HTTP_PARSE_INVALID || rc == HTTP_PARSE_CONTINUE) { continue; } if (rc == HTTP_PARSE_DONE) { break; } - if (rc == HTTP_PARSE_OK) { lua_pushlstring(L, parser.header_name, parser.header_name_idx); diff --git a/test/app-tap/http_client.test.lua b/test/app-tap/http_client.test.lua index 887395d..d9380c0 100755 --- a/test/app-tap/http_client.test.lua +++ b/test/app-tap/http_client.test.lua @@ -197,7 +197,7 @@ local function test_errors(test) end local function test_headers(test, url, opts) - test:plan(15) + test:plan(16) local http = client:new() local r = http:get(url .. 'headers', opts) test:is(type(r.headers["set-cookie"]), 'string', "set-cookie check") @@ -205,6 +205,7 @@ local function test_headers(test, url, opts) test:ok(r.headers["set-cookie"]:match("age = 17"), "set-cookie check") test:is(r.headers["content-type"], "application/json", "content-type check") test:is(r.headers["my_header"], "value1,value2", "other header check") + test:isnil(r.headers["11200ok"], "http status line not included in headers") test:is(r.cookies["likes"][1], "cheese", "cookie value check") test:ok(r.cookies["likes"][2][1]:match("Expires"), "cookie option check") test:ok(r.cookies["likes"][2][3]:match("HttpOnly"), "cookie option check") -- 2.7.4