[tarantool-patches] [PATCH 6/7] msgpack: allow to pass 'const char *' into decode()

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Wed May 15 02:06:24 MSK 2019


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)





More information about the Tarantool-patches mailing list