[tarantool-patches] [PATCH] httpc: fix bug with segfault by wrong headers
Roman Khabibov
roman.habibov at tarantool.org
Sun Jun 16 18:24:09 MSK 2019
There wasn't lua_istable() checking for field 'headers'.
Closes #4281
---
Branch: https://github.com/tarantool/tarantool/compare/romanhabibov/gh-4281-header
Issue: https://github.com/tarantool/tarantool/issues/4281
src/lua/httpc.c | 66 ++++++++++++++++++++-----------
test/app-tap/http_client.test.lua | 17 ++++++++
2 files changed, 61 insertions(+), 22 deletions(-)
diff --git a/src/lua/httpc.c b/src/lua/httpc.c
index bc8d498ba..bd6a7995e 100644
--- a/src/lua/httpc.c
+++ b/src/lua/httpc.c
@@ -133,6 +133,43 @@ parse_headers(lua_State *L, char *buffer, size_t len,
lua_settable(L, -3);
return 0;
}
+
+/**
+ * Process the Lua table of headers that lies 2 below the top of
+ * @a L Lua stack. In case of an error, push it on @a L.
+ *
+ * Added to reduce nesting.
+ *
+ * @param L Lua stack.
+ * @param req http request.
+ *
+ * @retval 0 on success.
+ * @retval non-zero on error.
+ */
+static int
+process_headers(struct lua_State *L, struct httpc_request *req)
+{
+ 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) {
+ httpc_request_delete(req);
+ return luaT_error(L);
+ }
+ lua_pop(L, 1);
+ }
+ return 0;
+}
+
/* }}}
*/
@@ -177,28 +214,13 @@ luaT_httpc_request(lua_State *L)
lua_getfield(L, 5, "headers");
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) {
- httpc_request_delete(req);
- return luaT_error(L);
- }
- lua_pop(L, 1);
- }
+ int ret;
+ if (lua_istable(L, -2) != 0)
+ ret = process_headers(L, req);
+ else
+ return luaL_error(L, "field \"headers\" must be table");
+ if (ret != 0)
+ return ret;
}
lua_pop(L, 1);
diff --git a/test/app-tap/http_client.test.lua b/test/app-tap/http_client.test.lua
index 680c78b35..9cb8c3a74 100755
--- a/test/app-tap/http_client.test.lua
+++ b/test/app-tap/http_client.test.lua
@@ -276,6 +276,7 @@ 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 exp_err_non_table = 'field "headers" must be table'
local cases = {
{
'string header',
@@ -324,6 +325,22 @@ local function test_request_headers(test, url, opts)
opts = {headers = {aaa = setmetatable({}, {})}},
exp_err = exp_err,
},
+-- gh-4281 allow only field 'headers' can be table
+ {
+ 'non-table \'headers\'',
+ opts = {headers = 'aaa'},
+ exp_err = exp_err_non_table,
+ },
+ {
+ 'non-table \'headers\'',
+ opts = {headers = 1},
+ exp_err = exp_err_non_table,
+ },
+ {
+ 'non-table \'headers\'',
+ opts = {headers = box.NULL},
+ exp_err = exp_err_non_table,
+ },
}
test:plan(#cases)
--
2.20.1 (Apple Git-117)
More information about the Tarantool-patches
mailing list