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 0000000000000000000000000000000000000000..e4878e2b31f873798e200c65a281a695f260cfaa
--- /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 a02376740f74c2888a17960a42829ca27d4c1ba6..da9ecea80a4dd3b52c0f812068061e0fa46d792a 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 0000000000000000000000000000000000000000..508249ad9469e56dbb7d028266e67369136d6de4
--- /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