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 064B426FB8 for ; Mon, 11 Feb 2019 18:24:15 -0500 (EST) 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 MyyRIhVScXcu for ; Mon, 11 Feb 2019 18:24:14 -0500 (EST) Received: from smtp3.mail.ru (smtp3.mail.ru [94.100.179.58]) (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 0C5CC248CB for ; Mon, 11 Feb 2019 18:24:13 -0500 (EST) Date: Tue, 12 Feb 2019 02:24:10 +0300 From: Roman Subject: [tarantool-patches] Re: [PATCH] httpc: add checking of headers in httpc:request Message-Id: <1549927450.14514.0@smtp.mail.ru> In-Reply-To: <2e5f83a6-2885-96f8-6fd6-a5fd34e32644@tarantool.org> References: <20181221181844.4417-1-roman.habibov@tarantool.org> <20181223031929.hhmxdlsox2aon5ih@tkn_work_nb> <3b2626ce-b887-70dd-38b0-ef38b37a983c@tarantool.org> <72bbdfde-54d7-0e94-c5e7-ca84c2a6078d@tarantool.org> <7f31300f-2e4a-f0b1-a40c-90d631fb9778@tarantool.org> <2e5f83a6-2885-96f8-6fd6-a5fd34e32644@tarantool.org> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="=-NSBTK80PiqOijlhJwrBm" 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: tarantool-patches@freelists.org Cc: Vladislav Shpilevoy --=-NSBTK80PiqOijlhJwrBm Content-Type: text/plain; charset=iso-8859-5; format=flowed Content-Transfer-Encoding: quoted-printable Hi! Thanks for review. On =B2=E2, =E4=D5=D2 5, 2019 at 2:42 PM, Vladislav Shpilevoy=20 wrote: > Hi! Thanks for the fixes! See 3 comments below. >=20 >>> 4. In the commit message you said that 'nil' is ok, but here you=20 >>> did not >>> check for that and return an error. Of course, real nil can not=20 >>> appear in >>> a table, because it means absence of a value, but what about=20 >>> box.NULL? >>=20 >> Added test for this case, right? >=20 > 1. Yes, you did, but the test fails. On my laptop http_client.test.lua > is totally broken for already a year at least, but I run the test from > console and got this: >=20 > tarantool> client =3D require('http.client') > --- > ... >=20 > tarantool> http =3D client:new() > --- > ... >=20 > tarantool> opts =3D {headers =3D {aaa =3D box.NULL}} > --- > ... >=20 > tarantool> http:get('127.0.0.1:12345', opts) > --- > - error: 'builtin/http.client.lua:299: can''t convert header to a=20 > string' >=20 > So box.NULL is not converted to string despite the fact that box.NULL=20 > =3D=3D nil > and you said in the commit message >=20 > "... Each header must be nil, 'string' or 'table' ..." In a private chat, we decided that this result is ok. And I changed the=20 commit message. >>> 5. Out of 80 symbols. >=20 > 2. Still out of 80. My text editor shows 70 symbols. >>>> + } else if (luaL_getmetafield(L, -1, "__tostring")=20 >>>> =3D=3D LUA_TNIL) { >> diff --git a/test/app-tap/http_client.test.lua=20 >> b/test/app-tap/http_client.test.lua >> index 10a3728f8..f231c2e90 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 >>=20 >> +-- gh-3679 allow only headers can be converted to string >=20 > 3. I am not a linguist, but the sentence looks grammatically > incorrect IMO. 'Allow only headers can be ...=20 > '. >=20 >> +local function test_request_headers(test, url, opts) >> + local exp_err =3D 'can\'t convert header to a string' >> + local cases =3D { >> + { + if (header_type !=3D LUA_TTABLE) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + } else if (!luaL_getmetafield(L, -1, "__tostring")) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + } Done like other error messages in this file. But I do not know how best=20 to fit code in 80 symbols. commit 104dbc419aaf3d9ec8f294513c73a98d2f103459 Author: Roman Khabibov 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=20 'string' or 'table' with '__tostring' metamethod. Closes #3679 diff --git a/src/lua/httpc.c b/src/lua/httpc.c index 5f4e2e912..bc89a2334 100644 --- a/src/lua/httpc.c +++ b/src/lua/httpc.c @@ -173,6 +173,17 @@ luaT_httpc_request(lua_State *L) if (!lua_isnil(L, -1)) { lua_pushnil(L); while (lua_next(L, -2) !=3D 0) { + int header_type =3D lua_type(L, -1); + if (header_type !=3D LUA_TSTRING) { + if (header_type !=3D LUA_TTABLE) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + } else if (!luaL_getmetafield(L, -1, "__tostring")) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + } + 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=20 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 =3D 'headers must be string or table with "__tostring"' + local cases =3D { + { + 'string header', + opts =3D {headers =3D {aaa =3D 'aaa'}}, + exp_err =3D nil, + }, + { + 'header with __tostring() metamethod', + opts =3D {headers =3D {aaa =3D setmetatable({}, { + __tostring =3D function(self) + return 'aaa' + end})}}, + exp_err =3D nil, + postrequest_check =3D function(opts) + assert(type(opts.headers.aaa) =3D=3D 'table', + '"aaa" header was modified in http_client') + end, + }, + { + 'boolean header', + opts =3D {headers =3D {aaa =3D true}}, + exp_err =3D exp_err, + }, + { + 'number header', + opts =3D {headers =3D {aaa =3D 10}}, + exp_err =3D exp_err, + }, + { + 'cdata header (box.NULL)', + opts =3D {headers =3D {aaa =3D box.NULL}}, + exp_err =3D exp_err, + }, + { + 'cdata header', + opts =3D {headers =3D {aaa =3D 10ULL}}, + exp_err =3D exp_err, + }, + { + 'table header w/o metatable', + opts =3D {headers =3D {aaa =3D {}}}, + exp_err =3D exp_err, + }, + { + 'table header w/o __tostring() metamethod', + opts =3D {headers =3D {aaa =3D setmetatable({}, {})}}, + exp_err =3D exp_err, + }, + } + test:plan(#cases) + + local http =3D client:new() + + for _, case in ipairs(cases) do + local opts =3D merge(table.copy(opts), case.opts) + local ok, err =3D pcall(http.get, http, url, opts) + if case.postrequest_check ~=3D nil then + case.postrequest_check(opts) + end + if case.exp_err =3D=3D nil then + -- expect success + test:ok(ok, case[1]) + else + -- expect fail + assert(type(err) =3D=3D 'string') + err =3D 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 =3D 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 =3D start_server(test, sock_family,=20 sock_addr) test:test("http.client", test_http_client, url, opts) test:test("cancel and errinj", test_cancel_and_errinj, url ..=20 '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 =3D=3D 'AF_UNIX' and jit.os ~=3D "Linux" then = --=-NSBTK80PiqOijlhJwrBm Content-Type: text/html; charset=iso-8859-5 Content-Transfer-Encoding: quoted-printable
Hi! Thanks for review.

On =B2=E2, =E4=D5=D2 5, 2019 at 2:42 PM, Vladislav Shpilevoy= <v.shpilevoy@tarantool.org> wrote:
Hi! Thanks for the fi= xes! See 3 comments below.
4. In the commit message you said that 'nil' is ok,= but here you did not check for that and return an error. Of course, real nil can not appear in a table, because it means absence of a value, but what about box.NULL?
Added test for this case, right?
1. Yes, you did, but the test fails. On my laptop http_client.test.lua is totally broken for already a year at least, but I run the test from console and got this: tarantool> client =3D require('http.client') --- ... tarantool> http =3D client:new() --- ... tarantool> opts =3D {headers =3D {aaa =3D box.NULL}} --- ... tarantool> http:get('127.0.0.1:12345', opts) --- - error: 'builtin/http.client.lua:299: can''t convert header to a string' So box.NULL is not converted to string despite the fact that box.NULL =3D= =3D nil and you said in the commit message "... Each header must be nil, 'string' or 'table' ..."
In a private chat, we decided= that this result is ok. And I changed the commit message.

5. Out of 80 symbols.
2. Still out of 80.My text editor shows 70 symbo= ls.
+&n= bsp;               }= else if (luaL_getmetafield(L, -1, "__tostring") =3D=3D LUA_TNIL) {
diff --git a/test/app-tap/http_client.test.lua b/= test/app-tap/http_client.test.lua index 10a3728f8..f231c2e90 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
3. I am not a linguist, but the sentence looks grammatically incorrect IMO. 'Allow only headers <something is missing> can be ... = '.
+local function test_request_headers(test, url, opts) +    local exp_err =3D 'can\'t convert header to a string' +    local cases =3D { +        {
+ if (header_type !=3D LUA_TTAB= LE) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + } else if (!luaL_getmetafield(L, -1, "__tostring")) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + }
Done like othe= r error messages in this file. But I do not know how best to fit code in 80= symbols.


commit 104dbc419aaf3d9ec8f294513c73a98d2f103459 Author: Roman Khabibov <roman.habibov@tarantool.org> Date: Wed Dec 26 17:49:34 2018 +0300 httpc: add checking of headers in httpc:request =20 Add preprocessing of the request headers. Each header must be 'string' = or 'table' with '__tostring' metamethod. =20 Closes #3679 diff --git a/src/lua/httpc.c b/src/lua/httpc.c index 5f4e2e912..bc89a2334 100644 --- a/src/lua/httpc.c +++ b/src/lua/httpc.c @@ -173,6 +173,17 @@ luaT_httpc_request(lua_State *L) if (!lua_isnil(L, -1)) { lua_pushnil(L); while (lua_next(L, -2) !=3D 0) { + int header_type =3D lua_type(L, -1); + if (header_type !=3D LUA_TSTRING) { + if (header_type !=3D LUA_TTABLE) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + } else if (!luaL_getmetafield(L, -1, "__tostring")) { + return luaL_error(L, + "headers must be string or table with \"__tostring\""); + } + 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.t= est.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 =20 +-- gh-3679 allow only headers can be converted to string +local function test_request_headers(test, url, opts) + local exp_err =3D 'headers must be string or table with "__tostring"' + local cases =3D { + { + 'string header', + opts =3D {headers =3D {aaa =3D 'aaa'}}, + exp_err =3D nil, + }, + { + 'header with __tostring() metamethod', + opts =3D {headers =3D {aaa =3D setmetatable({}, { + __tostring =3D function(self) + return 'aaa' + end})}}, + exp_err =3D nil, + postrequest_check =3D function(opts) + assert(type(opts.headers.aaa) =3D=3D 'table', + '"aaa" header was modified in http_client') + end, + }, + { + 'boolean header', + opts =3D {headers =3D {aaa =3D true}}, + exp_err =3D exp_err, + }, + { + 'number header', + opts =3D {headers =3D {aaa =3D 10}}, + exp_err =3D exp_err, + }, + { + 'cdata header (box.NULL)', + opts =3D {headers =3D {aaa =3D box.NULL}}, + exp_err =3D exp_err, + }, + { + 'cdata<uint64_t> header', + opts =3D {headers =3D {aaa =3D 10ULL}}, + exp_err =3D exp_err, + }, + { + 'table header w/o metatable', + opts =3D {headers =3D {aaa =3D {}}}, + exp_err =3D exp_err, + }, + { + 'table header w/o __tostring() metamethod', + opts =3D {headers =3D {aaa =3D setmetatable({}, {})}}, + exp_err =3D exp_err, + }, + } + test:plan(#cases) + + local http =3D client:new() + + for _, case in ipairs(cases) do + local opts =3D merge(table.copy(opts), case.opts) + local ok, err =3D pcall(http.get, http, url, opts) + if case.postrequest_check ~=3D nil then + case.postrequest_check(opts) + end + if case.exp_err =3D=3D nil then + -- expect success + test:ok(ok, case[1]) + else + -- expect fail + assert(type(err) =3D=3D 'string') + err =3D 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 =3D client:new() @@ -397,12 +471,13 @@ local function test_concurrent(test, url, opts) end =20 function run_tests(test, sock_family, sock_addr) - test:plan(9) + test:plan(10) local server, url, opts =3D 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_qu= ery', 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 =3D=3D 'AF_UNIX' and jit.os ~=3D "Linux" then

<= /div>
= --=-NSBTK80PiqOijlhJwrBm--