[tarantool-patches] [PATCH 1/3] sql: EXPLAIN through net.box leads to SEGFAULT
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Mon Nov 19 16:47:28 MSK 2018
From: Mergen Imeev <imeevma at gmail.com>
EXPLAIN envokes SEGMENTATION FAULT when being executed through
net.box. It happens due to column type of the result of this
function being NULL.
---
src/box/execute.c | 22 ++++++++++++++--------
src/box/lua/net_box.c | 15 ++++++++-------
test/sql/iproto.result | 15 +++++++++++++++
test/sql/iproto.test.lua | 13 ++++++++++++-
4 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/src/box/execute.c b/src/box/execute.c
index e45044488..5b747cf7f 100644
--- a/src/box/execute.c
+++ b/src/box/execute.c
@@ -529,9 +529,6 @@ sql_get_description(struct sqlite3_stmt *stmt, struct obuf *out,
return -1;
for (int i = 0; i < column_count; ++i) {
- size_t size = mp_sizeof_map(2) +
- mp_sizeof_uint(IPROTO_FIELD_NAME) +
- mp_sizeof_uint(IPROTO_FIELD_TYPE);
const char *name = sqlite3_column_name(stmt, i);
const char *type = sqlite3_column_datatype(stmt, i);
/*
@@ -540,18 +537,27 @@ sql_get_description(struct sqlite3_stmt *stmt, struct obuf *out,
* column_name simply returns them.
*/
assert(name != NULL);
- size += mp_sizeof_str(strlen(name));
- size += mp_sizeof_str(strlen(type));
+ size_t size = mp_sizeof_uint(IPROTO_FIELD_NAME) +
+ mp_sizeof_str(strlen(name));
+ if (type != NULL) {
+ size += mp_sizeof_map(2) +
+ mp_sizeof_uint(IPROTO_FIELD_TYPE) +
+ mp_sizeof_str(strlen(type));
+ } else {
+ size += mp_sizeof_map(1);
+ }
char *pos = (char *) obuf_alloc(out, size);
if (pos == NULL) {
diag_set(OutOfMemory, size, "obuf_alloc", "pos");
return -1;
}
- pos = mp_encode_map(pos, 2);
+ pos = mp_encode_map(pos, 1 + (type != NULL));
pos = mp_encode_uint(pos, IPROTO_FIELD_NAME);
pos = mp_encode_str(pos, name, strlen(name));
- pos = mp_encode_uint(pos, IPROTO_FIELD_TYPE);
- pos = mp_encode_str(pos, type, strlen(type));
+ if (type != NULL) {
+ pos = mp_encode_uint(pos, IPROTO_FIELD_TYPE);
+ pos = mp_encode_str(pos, type, strlen(type));
+ }
}
return 0;
}
diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index c7063d9c8..342c6a768 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -644,8 +644,7 @@ netbox_decode_metadata(struct lua_State *L, const char **data)
lua_createtable(L, count, 0);
for (uint32_t i = 0; i < count; ++i) {
uint32_t map_size = mp_decode_map(data);
- assert(map_size == 2);
- (void) map_size;
+ assert(map_size == 1 || map_size == 2);
uint32_t key = mp_decode_uint(data);
assert(key == IPROTO_FIELD_NAME);
(void) key;
@@ -654,11 +653,13 @@ netbox_decode_metadata(struct lua_State *L, const char **data)
const char *str = mp_decode_str(data, &len);
lua_pushlstring(L, str, len);
lua_setfield(L, -2, "name");
- key = mp_decode_uint(data);
- assert(key == IPROTO_FIELD_TYPE);
- const char *type = mp_decode_str(data, &len);
- lua_pushlstring(L, type, len);
- lua_setfield(L, -2, "type");
+ if (map_size == 2) {
+ key = mp_decode_uint(data);
+ assert(key == IPROTO_FIELD_TYPE);
+ const char *type = mp_decode_str(data, &len);
+ lua_pushlstring(L, type, len);
+ lua_setfield(L, -2, "type");
+ }
lua_rawseti(L, -2, i + 1);
}
}
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index d077ee861..31e5d2e75 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -773,6 +773,21 @@ cn:execute('drop table test')
cn:close()
---
...
+--
+-- EXPLAIN could lead to segfault because it does not send column
+-- data type, but looks like DQL. Netbox had been trying to decode
+-- type for any DQL.
+--
+cn = remote.connect(box.cfg.listen)
+---
+...
+-- Segmentation fault when EXPLAIN executed using net.box.
+_ = cn:execute("EXPLAIN SELECT 1;")
+---
+...
+cn:close()
+---
+...
box.schema.user.revoke('guest', 'read,write,execute', 'universe')
---
...
diff --git a/test/sql/iproto.test.lua b/test/sql/iproto.test.lua
index 1470edad7..a0f0f15ee 100644
--- a/test/sql/iproto.test.lua
+++ b/test/sql/iproto.test.lua
@@ -247,10 +247,21 @@ cn:execute('drop table test')
cn:close()
+--
+-- EXPLAIN could lead to segfault because it does not send column
+-- data type, but looks like DQL. Netbox had been trying to decode
+-- type for any DQL.
+--
+cn = remote.connect(box.cfg.listen)
+
+-- Segmentation fault when EXPLAIN executed using net.box.
+_ = cn:execute("EXPLAIN SELECT 1;")
+
+cn:close()
+
box.schema.user.revoke('guest', 'read,write,execute', 'universe')
box.schema.user.revoke('guest', 'create', 'space')
space = nil
-- Cleanup xlog
box.snapshot()
-
--
2.17.2 (Apple Git-113)
More information about the Tarantool-patches
mailing list