Tarantool development patches archive
 help / color / mirror / Atom feed
From: Roman Khabibov <roman.habibov@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH] httpc: add checking of headers in httpc:request
Date: Sun, 24 Feb 2019 01:43:36 +0300	[thread overview]
Message-ID: <C3DF11E4-144C-407B-998D-C2DC3B89D456@tarantool.org> (raw)
In-Reply-To: <dccea1b7-4f6f-78f7-446e-9ccf69b48fce@tarantool.org>

Hi! Thanks for review. 

On 2/22/19 7:01 PM, Vladislav Shpilevoy wrote: 


> Hi! Thanks for the fixes! See 3 comments below. 
> On 19/02/2019 13:49, Roman wrote: 
> 
>> Hi! Thanks for review. 
>> On Сб, фев 16, 2019 at 12:17 AM, Vladislav Shpilevoy 
>> <v.shpilevoy@tarantool.org> <mailto:v.shpilevoy@tarantool.org>
>>  wrote: 
>> 
>>> Hi! 
>>>          5. Out of 80 symbols. \x7f\x7f 2. Still out of 80. 
>>> 
>>>      My text editor shows 70 symbols. 
>>> 
>>> Then there is something wrong with your editor, sorry. 
>>> https://github.com/tarantool/tarantool/blob/romanhabibov/gh-3679-httpc-request/src/lua/httpc.c#L180 <https://github.com/tarantool/tarantool/blob/romanhabibov/gh-3679-httpc-request/src/lua/httpc.c#L180>
>>>  Lets count. Here you have 6 tabs - 6 * 8 = 48 symbols. Then you have 55 symbols of "headers must be string or table with \"__tostring\""); 48 + 55 = 103. Also, the error string is not aligned by opening parenthesis. In your email I see, that you have 4 symbols tab, what gives you 79 symbols, but tab width in this file should be 8. So probably you mistakenly set tab width to 4 and the editor shows you < 80 width. Please, fix. 
>>> 
>> Ok. Done. 
>> 
> 1. Now you have leading whitespace on line 182. It is clearly visible in 
> git diff as a bright red point. Please, do self-review before sending 
> a patch. 
> 
I'm sorry to waste your time. I was in a hurry and did't notice. 



>> commit c9802592b27cb6986e3e72eb948d8dbfb21baa7e 
>> Author: Roman Khabibov 
>> <roman.habibov@tarantool.org> <mailto:roman.habibov@tarantool.org>
>>  
>> Date: Wed Dec 26 17:49:34 2018 +0300 
>> httpc: add checking of headers in httpc:request 
>> Add preprocessing of the request headers. Each header must be 'string' or 'table' 
>> with '__tostring' metamethod. 
>> Closes #3679 
>> diff --git a/src/lua/httpc.c b/src/lua/httpc.c 
>> index 5f4e2e912..fb012f58b 100644 
>> --- a/src/lua/httpc.c 
>> +++ b/src/lua/httpc.c 
>> @@ -173,6 +173,18 @@ luaT_httpc_request(lua_State *L) 
>> if (!lua_isnil(L, -1)) { 
>> lua_pushnil(L); 
>> while (lua_next(L, -2) != 0) { 
>> + int header_type = lua_type(L, -1); 
>> + if (header_type != LUA_TSTRING) { 
>> + char *err_msg = "headers must be " \ 
>> + "string or table with \"__tostring\""; 
>> 
> 2. Please, do not assign a const char string to 
> a 'char *' variable. Use 'const char *'. Also, 
> please, properly align strings. This part should 
> look like this: 
>              if (header_type != LUA_TSTRING) { 
>                  const char *err_msg = 
>                      "headers must be string or table with "\ 
>                      "\"__tostring\""; 
>                  if (header_type != LUA_TTABLE) { 
> Wrapped string is aligned by the beginning. 
> 
>> + if (header_type != LUA_TTABLE) { 
>> + return luaL_error(L, err_msg); 
>> + } else if (!luaL_getmetafield(L, -1, 
>> + "__tostring")) { 
>> + return luaL_error(L, err_msg); 
>> + } 
>> + lua_pop(L, 1); 
>> + } 
>> 
Done.


commit 42d25f4d6eef69ae56db3841863afa3373fa9b67
Author: Roman Khabibov <roman.habibov@tarantool.org>
Date:   Wed Dec 26 17:49:34 2018 +0300

    httpc: add checking of headers in httpc:request
    
    Add preprocessing of the request headers. Each header must be 'string' or 'table'
    with '__tostring' metamethod.
    
    Closes #3679

diff --git a/src/lua/httpc.c b/src/lua/httpc.c
index 5f4e2e912..db8634949 100644
--- a/src/lua/httpc.c
+++ b/src/lua/httpc.c
@@ -173,6 +173,19 @@ luaT_httpc_request(lua_State *L)
 	if (!lua_isnil(L, -1)) {
 		lua_pushnil(L);
 		while (lua_next(L, -2) != 0) {
+			int header_type = lua_type(L, -1);
+			if (header_type != LUA_TSTRING) {
+				const char *err_msg =
+					"headers must be string or table "\
+					"with \"__tostring\"";
+				if (header_type != LUA_TTABLE) {
+					return luaL_error(L, err_msg);
+				} else if (!luaL_getmetafield(L, -1,
+							      "__tostring")) {
+					return luaL_error(L, err_msg);
+				}
+				lua_pop(L, 1);
+			}
 			if (httpc_set_header(req, "%s: %s",
 					     lua_tostring(L, -2),
 					     lua_tostring(L, -1)) < 0) {
diff --git a/test/app-tap/http_client.test.lua b/test/app-tap/http_client.test.lua
index 10a3728f8..8a98d1e92 100755
--- a/test/app-tap/http_client.test.lua
+++ b/test/app-tap/http_client.test.lua
@@ -205,6 +205,80 @@ local function test_errors(test)
     test:is(r.status, 595, "GET: response on bad url")
 end
 
+-- gh-3679 allow only headers can be converted to string
+local function test_request_headers(test, url, opts)
+    local exp_err = 'headers must be string or table with "__tostring"'
+    local cases = {
+        {
+            'string header',
+            opts = {headers = {aaa = 'aaa'}},
+            exp_err = nil,
+        },
+        {
+            'header with __tostring() metamethod',
+            opts = {headers = {aaa = setmetatable({}, {
+                __tostring = function(self)
+                    return 'aaa'
+                end})}},
+            exp_err = nil,
+            postrequest_check = function(opts)
+                assert(type(opts.headers.aaa) == 'table',
+                    '"aaa" header was modified in http_client')
+            end,
+        },
+        {
+            'boolean header',
+            opts = {headers = {aaa = true}},
+            exp_err = exp_err,
+        },
+        {
+            'number header',
+            opts = {headers = {aaa = 10}},
+            exp_err = exp_err,
+        },
+        {
+            'cdata header (box.NULL)',
+            opts = {headers = {aaa = box.NULL}},
+            exp_err = exp_err,
+        },
+        {
+            'cdata<uint64_t> header',
+            opts = {headers = {aaa = 10ULL}},
+            exp_err = exp_err,
+        },
+        {
+            'table header w/o metatable',
+            opts = {headers = {aaa = {}}},
+            exp_err = exp_err,
+        },
+        {
+            'table header w/o __tostring() metamethod',
+            opts = {headers = {aaa = setmetatable({}, {})}},
+            exp_err = exp_err,
+        },
+    }
+    test:plan(#cases)
+
+    local http = client:new()
+
+    for _, case in ipairs(cases) do
+        local opts = merge(table.copy(opts), case.opts)
+        local ok, err = pcall(http.get, http, url, opts)
+        if case.postrequest_check ~= nil then
+            case.postrequest_check(opts)
+        end
+        if case.exp_err == nil then
+            -- expect success
+            test:ok(ok, case[1])
+        else
+            -- expect fail
+            assert(type(err) == 'string')
+            err = err:gsub('^builtin/[a-z._]+.lua:[0-9]+: ', '')
+            test:is_deeply({ok, err}, {false, case.exp_err}, case[1])
+        end
+    end
+end
+
 local function test_headers(test, url, opts)
     test:plan(19)
     local http = client:new()
@@ -397,12 +471,13 @@ local function test_concurrent(test, url, opts)
 end
 
 function run_tests(test, sock_family, sock_addr)
-    test:plan(9)
+    test:plan(10)
     local server, url, opts = start_server(test, sock_family, sock_addr)
     test:test("http.client", test_http_client, url, opts)
     test:test("cancel and errinj", test_cancel_and_errinj, url .. 'long_query', opts)
     test:test("basic http post/get", test_post_and_get, url, opts)
     test:test("errors", test_errors)
+    test:test("request_headers", test_request_headers, url, opts)
     test:test("headers", test_headers, url, opts)
     test:test("special methods", test_special_methods, url, opts)
     if sock_family == 'AF_UNIX' and jit.os ~= "Linux" then

  parent reply	other threads:[~2019-02-23 22:43 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-21 18:18 [tarantool-patches] " Roman Khabibov
2018-12-23  3:19 ` [tarantool-patches] " Alexander Turenko
2018-12-26 15:56   ` Roman
2018-12-29 10:30     ` Vladislav Shpilevoy
2019-01-09 13:29       ` Roman
2019-01-24 14:54         ` Roman
2019-01-29 19:44         ` Vladislav Shpilevoy
2019-01-29 20:32           ` Alexander Turenko
2019-01-31 23:47           ` Roman
2019-02-05 11:42             ` Vladislav Shpilevoy
2019-02-11 23:24               ` Roman
2019-02-15 21:17                 ` Vladislav Shpilevoy
2019-02-19 10:49                   ` Roman
2019-02-22 16:01                     ` Vladislav Shpilevoy
2019-02-23 21:38                       ` Roman Khabibov
2019-02-23 22:43                       ` Roman Khabibov [this message]
2019-02-25 13:04                         ` Vladislav Shpilevoy
2019-02-25 14:51 ` Kirill Yukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=C3DF11E4-144C-407B-998D-C2DC3B89D456@tarantool.org \
    --to=roman.habibov@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='[tarantool-patches] Re: [PATCH] httpc: add checking of headers in httpc:request' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox