diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index f15d270518096b549f27cd969af628235101a80a..c3c14bd226fc74385d19ffbff85798c55342db60 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -175,7 +175,8 @@ port_vdbemem_get_msgpack(struct port *base, uint32_t *size)
 		}
 		case MP_STR: {
 			const char *str = (const char *) sql_value_text(param);
-			mpstream_encode_str(&stream, str);
+			mpstream_encode_strn(&stream, str,
+					     sql_value_bytes(param));
 			break;
 		}
 		case MP_BIN:
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 7fe078835cc89e1a5f5152e7599cf492a271ff34..7276996d953d3e627ef02d2116269ce09ed02560 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -62,6 +62,7 @@ add_subdirectory(app)
 add_subdirectory(app-tap)
 add_subdirectory(box)
 add_subdirectory(box-tap)
+add_subdirectory(sql-tap)
 if(ENABLE_FUZZER)
     add_subdirectory(fuzz)
 endif()
diff --git a/test/sql-tap/CMakeLists.txt b/test/sql-tap/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6e2eae2ff189581478c1f85f0e73e41d591ce259
--- /dev/null
+++ b/test/sql-tap/CMakeLists.txt
@@ -0,0 +1,2 @@
+include_directories(${MSGPUCK_INCLUDE_DIRS})
+build_module(gh-5938-wrong-string-length gh-5938-wrong-string-length.c)
diff --git a/test/sql-tap/gh-5938-wrong-string-length.c b/test/sql-tap/gh-5938-wrong-string-length.c
new file mode 100644
index 0000000000000000000000000000000000000000..e53163fd2d89ba957b9b4ef6adf2ac2c799c6fad
--- /dev/null
+++ b/test/sql-tap/gh-5938-wrong-string-length.c
@@ -0,0 +1,41 @@
+#include "msgpuck.h"
+#include "module.h"
+
+enum {
+	BUF_SIZE = 512,
+};
+
+int
+ret_str(box_function_ctx_t *ctx, const char *args, const char *args_end)
+{
+	uint32_t arg_count = mp_decode_array(&args);
+	if (arg_count != 1) {
+		return box_error_set(__FILE__, __LINE__, ER_PROC_C,
+				     "invalid argument count");
+	}
+	if (mp_typeof(*args) != MP_STR) {
+		return box_error_set(__FILE__, __LINE__, ER_PROC_C,
+				     "argument should be string");
+	}
+	const char* str;
+	uint32_t str_n;
+	str = mp_decode_str(&args, &str_n);
+
+	uint32_t size = mp_sizeof_array(1) + mp_sizeof_str(str_n);
+	if (size > BUF_SIZE) {
+		return box_error_set(__FILE__, __LINE__, ER_PROC_C,
+				     "string is too long");
+	}
+
+	char tuple_buf[BUF_SIZE];
+	char *d = tuple_buf;
+	d = mp_encode_array(d, 1);
+	d = mp_encode_str(d, str, str_n);
+	assert(d <= tuple_buf + size);
+
+	box_tuple_format_t *fmt = box_tuple_format_default();
+	box_tuple_t *tuple = box_tuple_new(fmt, tuple_buf, d);
+	if (tuple == NULL)
+		return -1;
+	return box_return_tuple(ctx, tuple);
+}
diff --git a/test/sql-tap/gh-5938-wrong-string-length.test.lua b/test/sql-tap/gh-5938-wrong-string-length.test.lua
new file mode 100755
index 0000000000000000000000000000000000000000..943389e3450c839df8d2273b0cd63644d012b339
--- /dev/null
+++ b/test/sql-tap/gh-5938-wrong-string-length.test.lua
@@ -0,0 +1,28 @@
+#!/usr/bin/env tarantool
+local build_path = os.getenv("BUILDDIR")
+package.cpath = build_path..'/test/sql-tap/?.so;'..build_path..'/test/sql-tap/?.dylib;'..package.cpath
+
+local test = require("sqltester")
+test:plan(1)
+
+box.schema.func.create("gh-5938-wrong-string-length.ret_str", {
+    language = "C",
+    param_list = { "string" },
+    returns = "string",
+    exports = { "LUA", "SQL" },
+    is_deterministic = true
+})
+
+test:execsql([[CREATE TABLE t (i INT PRIMARY KEY, s STRING);]])
+box.space.T:insert({1, 'This is a complete string'})
+box.space.T:insert({2, 'This is a cropped\0 string'})
+
+test:do_execsql_test(
+    "gh-5938-1",
+    [[
+        SELECT "gh-5938-wrong-string-length.ret_str"(s) from t;
+    ]], {
+        "This is a complete string","This is a cropped\0 string"
+    })
+
+test:finish_test()