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 05B4E2EA87 for ; Tue, 14 May 2019 19:06:32 -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 ubY0yhQHlpXK for ; Tue, 14 May 2019 19:06:31 -0400 (EDT) Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (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 B3CAE2EA7C for ; Tue, 14 May 2019 19:06:31 -0400 (EDT) From: Vladislav Shpilevoy Subject: [tarantool-patches] [PATCH 6/7] msgpack: allow to pass 'const char *' into decode() Date: Wed, 15 May 2019 02:06:24 +0300 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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: kostja@tarantool.org msgpack.decode() internally uses 'const char *' variable to decode msgpack, but somewhy expects only 'char *' as input. This commit allows to pass 'const char *' as well. --- src/lua/msgpack.c | 16 +++++----------- src/lua/utils.c | 20 +++++++++++++++++++- src/lua/utils.h | 11 +++++++++++ test/app-tap/msgpack.test.lua | 7 ++++--- test/app/msgpack.result | 18 ++++++++++++++++++ test/app/msgpack.test.lua | 7 +++++++ 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/lua/msgpack.c b/src/lua/msgpack.c index 73bda80ea..66b83b894 100644 --- a/src/lua/msgpack.c +++ b/src/lua/msgpack.c @@ -50,8 +50,6 @@ luamp_error(void *error_ctx) luaL_error(L, diag_last_error(diag_get())->errmsg); } -static uint32_t CTID_CHAR_PTR; - struct luaL_serializer *luaL_msgpack_default = NULL; static enum mp_type @@ -332,9 +330,8 @@ lua_msgpack_encode(lua_State *L) static int lua_msgpack_decode_cdata(lua_State *L, bool check) { - uint32_t ctypeid; - const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid); - if (ctypeid != CTID_CHAR_PTR) { + const char *data; + if (luaL_checkconstchar(L, 1, &data) != 0) { return luaL_error(L, "msgpack.decode: " "a Lua string or 'char *' expected"); } @@ -346,7 +343,7 @@ lua_msgpack_decode_cdata(lua_State *L, bool check) } struct luaL_serializer *cfg = luaL_checkserializer(L); luamp_decode(L, cfg, &data); - *(const char **)luaL_pushcdata(L, ctypeid) = data; + *(const char **)luaL_pushcdata(L, CTID_CHAR_PTR) = data; return 2; } @@ -435,9 +432,8 @@ verify_decode_header_args(lua_State *L, const char *func_name, return luaL_error(L, "Usage: %s(ptr, size)", func_name); /* Verify ptr type. */ - uint32_t ctypeid; - const char *data = *(char **) luaL_checkcdata(L, 1, &ctypeid); - if (ctypeid != CTID_CHAR_PTR) + const char *data; + if (luaL_checkconstchar(L, 1, &data) != 0) return luaL_error(L, "%s: 'char *' expected", func_name); /* Verify size type and value. */ @@ -525,8 +521,6 @@ lua_msgpack_new(lua_State *L) LUALIB_API int luaopen_msgpack(lua_State *L) { - CTID_CHAR_PTR = luaL_ctypeid(L, "char *"); - assert(CTID_CHAR_PTR != 0); luaL_msgpack_default = luaL_newserializer(L, "msgpack", msgpacklib); return 1; } diff --git a/src/lua/utils.c b/src/lua/utils.c index f53d7e588..01a0cd894 100644 --- a/src/lua/utils.c +++ b/src/lua/utils.c @@ -43,6 +43,8 @@ int luaL_array_metatable_ref = LUA_REFNIL; static uint32_t CTID_STRUCT_IBUF; static uint32_t CTID_STRUCT_IBUF_PTR; +uint32_t CTID_CHAR_PTR; +uint32_t CTID_CONST_CHAR_PTR; void * luaL_pushcdata(struct lua_State *L, uint32_t ctypeid) @@ -1076,6 +1078,19 @@ luaL_checkibuf(struct lua_State *L, int idx) return NULL; } +int +luaL_checkconstchar(struct lua_State *L, int idx, const char **res) +{ + if (lua_type(L, idx) != LUA_TCDATA) + return -1; + uint32_t cdata_type; + void *cdata = luaL_checkcdata(L, idx, &cdata_type); + if (cdata_type != CTID_CHAR_PTR && cdata_type != CTID_CONST_CHAR_PTR) + return -1; + *res = cdata != NULL ? *(const char **) cdata : NULL; + return 0; +} + lua_State * luaT_state(void) { @@ -1209,6 +1224,9 @@ tarantool_lua_utils_init(struct lua_State *L) assert(CTID_STRUCT_IBUF != 0); CTID_STRUCT_IBUF_PTR = luaL_ctypeid(L, "struct ibuf *"); assert(CTID_STRUCT_IBUF_PTR != 0); - + CTID_CHAR_PTR = luaL_ctypeid(L, "char *"); + assert(CTID_CHAR_PTR != 0); + CTID_CONST_CHAR_PTR = luaL_ctypeid(L, "const char *"); + assert(CTID_CONST_CHAR_PTR != 0); return 0; } diff --git a/src/lua/utils.h b/src/lua/utils.h index cf51eb132..3d887a5ce 100644 --- a/src/lua/utils.h +++ b/src/lua/utils.h @@ -67,6 +67,9 @@ struct ibuf; extern struct lua_State *tarantool_L; extern struct ibuf *tarantool_lua_ibuf; +extern uint32_t CTID_CONST_CHAR_PTR; +extern uint32_t CTID_CHAR_PTR; + /** \cond public */ /** @@ -544,6 +547,14 @@ luaL_checkfinite(struct lua_State *L, struct luaL_serializer *cfg, struct ibuf * luaL_checkibuf(struct lua_State *L, int idx); +/** + * Check if a value on @a L stack by index @a idx is pointer at + * char or const char. '(char *)NULL' is also considered a valid + * char pointer. + */ +int +luaL_checkconstchar(struct lua_State *L, int idx, const char **res); + /* {{{ Helper functions to interact with a Lua iterator from C */ /** diff --git a/test/app-tap/msgpack.test.lua b/test/app-tap/msgpack.test.lua index 1b0bb9806..bd095e5ae 100755 --- a/test/app-tap/msgpack.test.lua +++ b/test/app-tap/msgpack.test.lua @@ -57,6 +57,7 @@ local function test_decode_array_map_header(test, s) 'of buffer' local non_positive_size_err = 'msgpack.decode_[^_]+_header: ' .. 'non%-positive size' + local wrong_type_err = "msgpack.decode_[^_]+_header: 'char %*' expected" local decode_cases = { { @@ -175,17 +176,17 @@ local function test_decode_array_map_header(test, s) { 'data is nil', args = {nil, 1}, - exp_err = 'expected cdata as 1 argument', + exp_err = wrong_type_err, }, { 'data is not cdata', args = {1, 1}, - exp_err = 'expected cdata as 1 argument', + exp_err = wrong_type_err, }, { 'data with wrong cdata type', args = {box.tuple.new(), 1}, - exp_err = "msgpack.decode_[^_]+_header: 'char %*' expected", + exp_err = wrong_type_err, }, { 'size has wrong type', diff --git a/test/app/msgpack.result b/test/app/msgpack.result index 9fc42fc3c..105f503da 100644 --- a/test/app/msgpack.result +++ b/test/app/msgpack.result @@ -4,6 +4,9 @@ buffer = require 'buffer' msgpack = require 'msgpack' --- ... +ffi = require 'ffi' +--- +... -- Arguments check. buf = buffer.ibuf() --- @@ -226,3 +229,18 @@ size = msgpack.encode({c = 3, d = 4}, buf) --- - {'c': 3, 'd': 4} ... +-- Decode should accept both 'char *' and 'const char *'. +buf:reset() +--- +... +size = msgpack.encode(100, buf) +--- +... +(msgpack.decode(ffi.cast('char *', buf.rpos), size)) +--- +- 100 +... +(msgpack.decode(ffi.cast('const char *', buf.rpos), size)) +--- +- 100 +... diff --git a/test/app/msgpack.test.lua b/test/app/msgpack.test.lua index 0920fa507..de8fd4e37 100644 --- a/test/app/msgpack.test.lua +++ b/test/app/msgpack.test.lua @@ -1,5 +1,6 @@ buffer = require 'buffer' msgpack = require 'msgpack' +ffi = require 'ffi' -- Arguments check. buf = buffer.ibuf() @@ -71,3 +72,9 @@ size = msgpack.encode({a = 1, b = 2}, buf) buf = buffer.ibuf() size = msgpack.encode({c = 3, d = 4}, buf) (msgpack.decode(buf.rpos, size)) + +-- Decode should accept both 'char *' and 'const char *'. +buf:reset() +size = msgpack.encode(100, buf) +(msgpack.decode(ffi.cast('char *', buf.rpos), size)) +(msgpack.decode(ffi.cast('const char *', buf.rpos), size)) -- 2.20.1 (Apple Git-117)