From a281c7423a57fa1cda1fccd4fd05267e87240bdb Mon Sep 17 00:00:00 2001
From: Andrey Saranchin <Andrey22102001@gmail.com>
Date: Thu, 23 Sep 2021 13:39:08 +0300
Subject: [PATCH] memtx: raise an error if argument of select() is a "clear"
 dict

Currently, select/pairs/get look at an :array part of passed table,
that is why different problems occurs when passed to select() table
is not a regular array.

Now we will check if passed table is not "clear dict"
(not empty table without array part). Invalid queries
like s:select{key = 'value'} will fail with an appropriate
error, but the problems with dicts containing array part
still remain (for example, s:select{1, key = 'value'} is
the same as s:select{1}).

Closes #6167
---
 .../unreleased/gh-6167-select-with-dict.md    |  3 +++
 src/box/lua/tuple.lua                         |  9 +++++--
 test/box/gh-6167-select-with-dict.result      | 26 +++++++++++++++++++
 test/box/gh-6167-select-with-dict.test.lua    |  8 ++++++
 4 files changed, 44 insertions(+), 2 deletions(-)
 create mode 100644 changelogs/unreleased/gh-6167-select-with-dict.md
 create mode 100644 test/box/gh-6167-select-with-dict.result
 create mode 100644 test/box/gh-6167-select-with-dict.test.lua

diff --git a/changelogs/unreleased/gh-6167-select-with-dict.md b/changelogs/unreleased/gh-6167-select-with-dict.md
new file mode 100644
index 0000000000..edf2d1047b
--- /dev/null
+++ b/changelogs/unreleased/gh-6167-select-with-dict.md
@@ -0,0 +1,3 @@
+## bugfix/memtx
+
+* Now memtx will raise an error if "clear" dictionary was passed to s:select() (gh-6167)
diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua
index f47b5926d6..98f3f8de63 100644
--- a/src/box/lua/tuple.lua
+++ b/src/box/lua/tuple.lua
@@ -79,8 +79,13 @@ local tuple_encode = function(tmpbuf, obj)
     elseif is_tuple(obj) then
         encode_r(tmpbuf, obj, 1)
     elseif type(obj) == "table" then
-        encode_array(tmpbuf, #obj)
-        for i = 1, #obj, 1 do
+        local obj_size = #obj
+        if obj_size == 0 and not rawequal(next(obj), nil) then
+            -- dictionary cannot represent a tuple
+            return box.error(box.error.TUPLE_NOT_ARRAY)
+        end
+        encode_array(tmpbuf, obj_size)
+        for i = 1, obj_size, 1 do
             encode_r(tmpbuf, obj[i], 1)
         end
     else
diff --git a/test/box/gh-6167-select-with-dict.result b/test/box/gh-6167-select-with-dict.result
new file mode 100644
index 0000000000..249c18f99b
--- /dev/null
+++ b/test/box/gh-6167-select-with-dict.result
@@ -0,0 +1,26 @@
+-- test-run result file version 2
+s = box.schema.create_space('test')
+ | ---
+ | ...
+_ = s:create_index('pk')
+ | ---
+ | ...
+dict = {key = 'value'}
+ | ---
+ | ...
+-- There must be errors saying tuple must be array
+s:select(dict)
+ | ---
+ | - error: Tuple/Key must be MsgPack array
+ | ...
+s:pairs(dict)
+ | ---
+ | - error: Tuple/Key must be MsgPack array
+ | ...
+s:get(dict)
+ | ---
+ | - error: Tuple/Key must be MsgPack array
+ | ...
+s:drop()
+ | ---
+ | ...
diff --git a/test/box/gh-6167-select-with-dict.test.lua b/test/box/gh-6167-select-with-dict.test.lua
new file mode 100644
index 0000000000..2c440a6c5d
--- /dev/null
+++ b/test/box/gh-6167-select-with-dict.test.lua
@@ -0,0 +1,8 @@
+s = box.schema.create_space('test')
+_ = s:create_index('pk')
+dict = {key = 'value'}
+-- There must be errors saying tuple must be array
+s:select(dict)
+s:pairs(dict)
+s:get(dict)
+s:drop()
-- 
GitLab