From 6b79d50af6fab6f0d6d85e5cc2ecf5e64e17a9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A8=D0=B8=D0=BF=D0=B8=D1=86=D1=8B=D0=BD=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=82=D0=BE=D0=BB=D0=B8=D0=B9?= <avsh@get-net.ru> Date: Mon, 4 Feb 2019 17:36:45 +0500 Subject: [PATCH] httpc: increase max outgoing header size to 8 KiB The reason why the limit is so is that default Apache / nginx maximum header size is 8 KiB. Added a check to raise an error when a header is bigger then the limit. Fixes #3959. --- src/httpc.c | 9 ++++++++- test/app-tap/http_client.test.lua | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/httpc.c b/src/httpc.c index 950f8b32f6..e9f703ba1b 100644 --- a/src/httpc.c +++ b/src/httpc.c @@ -37,6 +37,8 @@ #include "fiber.h" #include "errinj.h" +#define MAX_HEADER_LEN 8192 + /** * libcurl callback for CURLOPT_WRITEFUNCTION * @see https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html @@ -173,9 +175,14 @@ httpc_request_delete(struct httpc_request *req) int httpc_set_header(struct httpc_request *req, const char *fmt, ...) { + static __thread char header[MAX_HEADER_LEN + 1]; va_list ap; va_start(ap, fmt); - const char *header = tt_vsprintf(fmt, ap); + int rc = vsnprintf(header, MAX_HEADER_LEN + 1, fmt, ap); + if (rc > MAX_HEADER_LEN) { + diag_set(IllegalParams, "header is too large"); + return -1; + } va_end(ap); struct curl_slist *l = curl_slist_append(req->headers, header); diff --git a/test/app-tap/http_client.test.lua b/test/app-tap/http_client.test.lua index 10a3728f87..6a4ec91773 100755 --- a/test/app-tap/http_client.test.lua +++ b/test/app-tap/http_client.test.lua @@ -206,7 +206,7 @@ local function test_errors(test) end local function test_headers(test, url, opts) - test:plan(19) + test:plan(21) local http = client:new() local r = http:get(url .. 'headers', opts) test:is(type(r.headers["set-cookie"]), 'string', "set-cookie check") @@ -231,6 +231,25 @@ local function test_headers(test, url, opts) local r = http:get(url .. 'headers', opts) test:is(r.headers["very_very_very_long_headers_name1"], "true", "truncated max_header_name_length") opts["max_header_name_length"] = nil + + -- Send large headers. + local MAX_HEADER_NAME = 8192 + local hname = 'largeheader' + + -- "${hname}: ${hvalue}" is 8192 bytes length + local hvalue = string.rep('x', MAX_HEADER_NAME - hname:len() - 2) + local headers = {[hname] = hvalue} + local r = http:post(url, nil, merge(opts, {headers = headers})) + test:is(r.headers[hname], hvalue, '8192 bytes header: success') + + -- "${hname}: ${hvalue}" is 8193 bytes length + local exp_err = 'header is too large' + local hvalue = string.rep('x', MAX_HEADER_NAME - hname:len() - 1) + local headers = {[hname] = hvalue} + local ok, err = pcall(http.post, http, url, nil, + merge(opts, {headers = headers})) + test:is_deeply({ok, tostring(err)}, {false, exp_err}, + '8193 KiB header: error') end local function test_special_methods(test, url, opts) -- GitLab