Tarantool development patches archive
 help / color / mirror / Atom feed
From: "Мерген Имеев" <imeevma@tarantool.org>
To: "Vladislav Shpilevoy" <v.shpilevoy@tarantool.org>
Cc: "n.pettik" <korablev@tarantool.org>, tarantool-patches@freelists.org
Subject: [tarantool-patches] Re[2]: [tarantool-patches] Re: [PATCH 1/3] sql: EXPLAIN through net.box leads to SEGFAULT
Date: Thu, 22 Nov 2018 23:55:22 +0300	[thread overview]
Message-ID: <1542920122.851013557@f398.i.mail.ru> (raw)
In-Reply-To: <6104171d-f355-733c-d01b-016127ec389a@tarantool.org>

[-- Attachment #1: Type: text/plain, Size: 11493 bytes --]

After discussion we decided that this patch will serve us
part of patch-set that should close newly filed bug:
https://github.com/tarantool/tarantool/issues/3832

The main Idea behind this ticket is that any statement
should return column type for when it returns column name.
And this ticket allow us to find an error without falling
into SEGMENTATION FAULT or returning less metadata.

Четверг, 22 ноября 2018, 21:31 +03:00 от Vladislav Shpilevoy <v.shpilevoy@tarantool.org>:
>
>It was just a question, "why did you decide to do not
>send type". It was not necessary to start sending UNKNOWN. I
>think, that unknown type should be sent never.
>
>On 22/11/2018 21:08, Imeev Mergen wrote:
>> Hi! Thank you for review! Diff between versions and new patch
>> below.
>> 
>> On 11/19/18 8:27 PM, n.pettik wrote:
>> 
>>>> EXPLAIN envokes SEGMENTATION FAULT when being executed through
>>> Typo: invokes.
>>>
>>>> net.box. It happens due to column type of the result of this
>>>> function being NULL.
>>> I’ve checked and not only EXPLAIN results, but also EXPLAIN QUERY PLAN,
>>> several pragmas (for instance, pragma table_info()) etc. So, initially problem
>>> was not only in EXPLAIN statement. Please exposed commit message and
>>> add tests on other cases.
>>>
>>> Also, why did you decide to avoid sending type at all, instead of sending
>>> UNKNOWN for example?
>> 
>> *Diff between versions:*
>> 
>> diff --git a/src/box/execute.c b/src/box/execute.c
>> index 5b747cf..cd809f8 100644
>> --- a/src/box/execute.c
>> +++ b/src/box/execute.c
>> @@ -529,6 +529,9 @@ 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);
>>           /*
>> @@ -537,27 +540,20 @@ sql_get_description(struct sqlite3_stmt *stmt, struct obuf *out,
>>            * column_name simply returns them.
>>            */
>>           assert(name != NULL);
>> -        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);
>> -        }
>> +        if (type == NULL)
>> +            type = "UNKNOWN";
>> +        size += mp_sizeof_str(strlen(name));
>> +        size += mp_sizeof_str(strlen(type));
>>           char *pos = (char *) obuf_alloc(out, size);
>>           if (pos == NULL) {
>>               diag_set(OutOfMemory, size, "obuf_alloc", "pos");
>>               return -1;
>>           }
>> -        pos = mp_encode_map(pos, 1 + (type != NULL));
>> +        pos = mp_encode_map(pos, 2);
>>           pos = mp_encode_uint(pos, IPROTO_FIELD_NAME);
>>           pos = mp_encode_str(pos, name, strlen(name));
>> -        if (type != NULL) {
>> -            pos = mp_encode_uint(pos, IPROTO_FIELD_TYPE);
>> -            pos = mp_encode_str(pos, type, strlen(type));
>> -        }
>> +        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 342c6a7..c7063d9 100644
>> --- a/src/box/lua/net_box.c
>> +++ b/src/box/lua/net_box.c
>> @@ -644,7 +644,8 @@ 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 == 1 || map_size == 2);
>> +        assert(map_size == 2);
>> +        (void) map_size;
>>           uint32_t key = mp_decode_uint(data);
>>           assert(key == IPROTO_FIELD_NAME);
>>           (void) key;
>> @@ -653,13 +654,11 @@ 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");
>> -        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");
>> -        }
>> +        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 31e5d2e..f229427 100644
>> --- a/test/sql/iproto.result
>> +++ b/test/sql/iproto.result
>> @@ -774,9 +774,9 @@ 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.
>> +-- Some commands, e.g. 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)
>>   ---
>> @@ -785,6 +785,32 @@ cn = remote.connect(box.cfg.listen)
>>   _ = cn:execute("EXPLAIN SELECT 1;")
>>   ---
>>   ...
>> +-- Segmentation fault when PRAGMA TABLE_INFO() executed using
>> +-- net.box.
>> +box.sql.execute('CREATE TABLE test (id INT PRIMARY KEY)')
>> +---
>> +...
>> +cn:execute("PRAGMA TABLE_INFO(test);")
>> +---
>> +- metadata:
>> +  - name: cid
>> +    type: UNKNOWN
>> +  - name: name
>> +    type: UNKNOWN
>> +  - name: type
>> +    type: UNKNOWN
>> +  - name: notnull
>> +    type: UNKNOWN
>> +  - name: dflt_value
>> +    type: UNKNOWN
>> +  - name: pk
>> +    type: UNKNOWN
>> +  rows:
>> +  - [0, 'ID', 'integer', 1, null, 1]
>> +...
>> +box.sql.execute('DROP TABLE test')
>> +---
>> +...
>>   cn:close()
>>   ---
>>   ...
>> diff --git a/test/sql/iproto.test.lua b/test/sql/iproto.test.lua
>> index a0f0f15..9bcc7ef 100644
>> --- a/test/sql/iproto.test.lua
>> +++ b/test/sql/iproto.test.lua
>> @@ -248,15 +248,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.
>> +-- Some commands, e.g. 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;")
>> 
>> +-- Segmentation fault when PRAGMA TABLE_INFO() executed using
>> +-- net.box.
>> +box.sql.execute('CREATE TABLE test (id INT PRIMARY KEY)')
>> +cn:execute("PRAGMA TABLE_INFO(test);")
>> +box.sql.execute('DROP TABLE test')
>> +
>>   cn:close()
>> 
>>   box.schema.user.revoke('guest', 'read,write,execute', 'universe')
>> 
>> 
>> *New version:*
>> 
>> commit 29dde0365922bfcec0d159b36c6454854adf34f7
>> Author: Mergen Imeev < imeevma@gmail.com >
>> Date:   Fri Nov 16 13:34:46 2018 +0300
>> 
>>      sql: Print column type even if it is NULL
>> 
>>      Some commands, e.g. EXPLAIN, invokes SEGMENTATION FAULT when being
>>      executed through net.box. It happens due to column type of the
>>      result of this function being NULL. This patch adds checks for
>>      received column type.
>> 
>> diff --git a/src/box/execute.c b/src/box/execute.c
>> index e450444..cd809f8 100644
>> --- a/src/box/execute.c
>> +++ b/src/box/execute.c
>> @@ -540,6 +540,8 @@ sql_get_description(struct sqlite3_stmt *stmt, struct obuf *out,
>>            * column_name simply returns them.
>>            */
>>           assert(name != NULL);
>> +        if (type == NULL)
>> +            type = "UNKNOWN";
>>           size += mp_sizeof_str(strlen(name));
>>           size += mp_sizeof_str(strlen(type));
>>           char *pos = (char *) obuf_alloc(out, size);
>> diff --git a/test/sql/iproto.result b/test/sql/iproto.result
>> index d077ee8..f229427 100644
>> --- a/test/sql/iproto.result
>> +++ b/test/sql/iproto.result
>> @@ -773,6 +773,47 @@ cn:execute('drop table test')
>>   cn:close()
>>   ---
>>   ...
>> +--
>> +-- Some commands, e.g. 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;")
>> +---
>> +...
>> +-- Segmentation fault when PRAGMA TABLE_INFO() executed using
>> +-- net.box.
>> +box.sql.execute('CREATE TABLE test (id INT PRIMARY KEY)')
>> +---
>> +...
>> +cn:execute("PRAGMA TABLE_INFO(test);")
>> +---
>> +- metadata:
>> +  - name: cid
>> +    type: UNKNOWN
>> +  - name: name
>> +    type: UNKNOWN
>> +  - name: type
>> +    type: UNKNOWN
>> +  - name: notnull
>> +    type: UNKNOWN
>> +  - name: dflt_value
>> +    type: UNKNOWN
>> +  - name: pk
>> +    type: UNKNOWN
>> +  rows:
>> +  - [0, 'ID', 'integer', 1, null, 1]
>> +...
>> +box.sql.execute('DROP TABLE test')
>> +---
>> +...
>> +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 1470eda..9bcc7ef 100644
>> --- a/test/sql/iproto.test.lua
>> +++ b/test/sql/iproto.test.lua
>> @@ -247,10 +247,27 @@ cn:execute('drop table test')
>> 
>>   cn:close()
>> 
>> +--
>> +-- Some commands, e.g. 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;")
>> +
>> +-- Segmentation fault when PRAGMA TABLE_INFO() executed using
>> +-- net.box.
>> +box.sql.execute('CREATE TABLE test (id INT PRIMARY KEY)')
>> +cn:execute("PRAGMA TABLE_INFO(test);")
>> +box.sql.execute('DROP TABLE test')
>> +
>> +cn:close()
>> +
>>   box.schema.user.revoke('guest', 'read,write,execute', 'universe')
>>   box.schema.user.revoke('guest', 'create', 'space')
>>   space = nil
>> 
>>   -- Cleanup xlog
>>   box.snapshot()
>> -
>> 


-- <br/>Мерген Имеев

[-- Attachment #2: Type: text/html, Size: 16463 bytes --]

  reply	other threads:[~2018-11-22 20:55 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-19 13:47 [tarantool-patches] [PATCH 0/3] A set of small SQL fixes Vladislav Shpilevoy
2018-11-19 13:47 ` [tarantool-patches] [PATCH 1/3] sql: EXPLAIN through net.box leads to SEGFAULT Vladislav Shpilevoy
2018-11-19 17:27   ` [tarantool-patches] " n.pettik
2018-11-22 18:08     ` Imeev Mergen
2018-11-22 18:31       ` Vladislav Shpilevoy
2018-11-22 20:55         ` Мерген Имеев [this message]
2018-11-23  6:04           ` [tarantool-patches] Re: Re[2]: " Kirill Yukhin
2018-11-28 12:36           ` [tarantool-patches] " n.pettik
2018-11-29 14:58             ` Konstantin Osipov
2018-11-19 13:47 ` [tarantool-patches] [PATCH 2/3] sql: SELECT from system spaces returns unpacked msgpack Vladislav Shpilevoy
2018-11-19 17:27   ` [tarantool-patches] " n.pettik
2018-11-22 18:09     ` Imeev Mergen
2018-11-27  8:51       ` n.pettik
2018-11-19 13:47 ` [tarantool-patches] [PATCH 3/3] sql: too many autogenerated ids leads to SEGFAULT Vladislav Shpilevoy
2018-11-19 17:27   ` [tarantool-patches] " n.pettik
2018-11-22 18:09     ` Imeev Mergen
2018-11-27  8:50       ` n.pettik
2018-11-27 10:09 ` [tarantool-patches] Re: [PATCH 0/3] A set of small SQL fixes Kirill Yukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1542920122.851013557@f398.i.mail.ru \
    --to=imeevma@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='[tarantool-patches] Re[2]: [tarantool-patches] Re: [PATCH 1/3] sql: EXPLAIN through net.box leads to SEGFAULT' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox