Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: Imeev Mergen <imeevma@tarantool.org>,
	"n.pettik" <korablev@tarantool.org>,
	tarantool-patches@freelists.org
Subject: [tarantool-patches] Re: [PATCH 1/3] sql: EXPLAIN through net.box leads to SEGFAULT
Date: Thu, 22 Nov 2018 21:31:14 +0300	[thread overview]
Message-ID: <6104171d-f355-733c-d01b-016127ec389a@tarantool.org> (raw)
In-Reply-To: <f5a6d3d2-b4bf-cbfb-e53c-b128ad497538@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()
> -
> 

  reply	other threads:[~2018-11-22 18:31 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 [this message]
2018-11-22 20:55         ` [tarantool-patches] Re[2]: " Мерген Имеев
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=6104171d-f355-733c-d01b-016127ec389a@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=imeevma@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[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