From 89057a21b5c1bb864f9f61adabd76b25af846a2c Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma@tarantool.org>
Date: Tue, 4 Oct 2022 13:20:15 +0300
Subject: [PATCH] sql: fix cursor invalidation

If the length of the tuple is greater than the number of fields in the
format, it is possible that the cursor in the VDBE will be overridden
with zeros.

Closes #5310

NO_DOC=bugfix
---
 .../gh-5310-fix-cursor-invalidation.md        |  4 ++++
 src/box/sql.c                                 |  9 ++++++-
 .../gh_5310_cursor_invalidation_test.lua      | 24 +++++++++++++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)
 create mode 100644 changelogs/unreleased/gh-5310-fix-cursor-invalidation.md
 create mode 100644 test/sql-luatest/gh_5310_cursor_invalidation_test.lua

diff --git a/changelogs/unreleased/gh-5310-fix-cursor-invalidation.md b/changelogs/unreleased/gh-5310-fix-cursor-invalidation.md
new file mode 100644
index 0000000000..e4878e2b31
--- /dev/null
+++ b/changelogs/unreleased/gh-5310-fix-cursor-invalidation.md
@@ -0,0 +1,4 @@
+## bugfix/sql
+
+* Fixed a crash that could occur when tuples longer than specified in
+  the format were selected (gh-5310).
diff --git a/src/box/sql.c b/src/box/sql.c
index a02376740f..da9ecea80a 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1377,8 +1377,15 @@ vdbe_field_ref_create(struct vdbe_field_ref *field_ref, struct tuple *tuple,
 	field_ref->data_sz = data_sz;
 
 	const char *field0 = data;
-	field_ref->field_count = mp_decode_array((const char **) &field0);
 	field_ref->format = NULL;
+	uint32_t mp_count = mp_decode_array(&field0);
+	if (tuple != NULL) {
+		assert(tuple_format(tuple) != NULL);
+		uint32_t field_count = tuple_format(tuple)->total_field_count;
+		field_ref->field_count = MIN(field_count, mp_count);
+	} else {
+		field_ref->field_count = mp_count;
+	}
 	field_ref->slots[0] = (uint32_t)(field0 - data);
 	memset(&field_ref->slots[1], 0,
 	       field_ref->field_count * sizeof(field_ref->slots[0]));
diff --git a/test/sql-luatest/gh_5310_cursor_invalidation_test.lua b/test/sql-luatest/gh_5310_cursor_invalidation_test.lua
new file mode 100644
index 0000000000..508249ad94
--- /dev/null
+++ b/test/sql-luatest/gh_5310_cursor_invalidation_test.lua
@@ -0,0 +1,24 @@
+local server = require('test.luatest_helpers.server')
+local t = require('luatest')
+local g = t.group()
+
+g.before_all(function()
+    g.server = server:new({alias = 'test_cursor_invalidation'})
+    g.server:start()
+end)
+
+g.after_all(function()
+    g.server:stop()
+end)
+
+g.test_cursor_invalidation = function()
+    g.server:exec(function()
+        local t = require('luatest')
+        local s = box.schema.space.create('T', {format = {'A'}})
+        s:create_index('ii')
+        s:insert({1,2,3,4,5})
+        s:insert({2})
+        t.assert_equals(box.execute([[SELECT * FROM t;]]).rows, {{1}, {2}})
+        s:drop()
+    end)
+end
-- 
GitLab