diff --git a/changelogs/unreleased/gh-5310-fix-cursor-invalidation.md b/changelogs/unreleased/gh-5310-fix-cursor-invalidation.md
index e4878e2b31f873798e200c65a281a695f260cfaa..1aa93a77e9efaefddc6ee1b67c70216271775652 100644
--- a/changelogs/unreleased/gh-5310-fix-cursor-invalidation.md
+++ b/changelogs/unreleased/gh-5310-fix-cursor-invalidation.md
@@ -1,4 +1,4 @@
 ## bugfix/sql
 
 * Fixed a crash that could occur when tuples longer than specified in
-  the format were selected (gh-5310).
+  the space format were selected (gh-5310, gh-4666).
diff --git a/src/box/ck_constraint.c b/src/box/ck_constraint.c
index af26da313aba56644dd8c8b95ac83842dae857d2..9648ea2a8a2e4d46ee6365e9a3216e5c38968544 100644
--- a/src/box/ck_constraint.c
+++ b/src/box/ck_constraint.c
@@ -200,6 +200,7 @@ ck_constraint_on_replace_trigger(struct trigger *trigger, void *event)
 			 "field_ref");
 		return -1;
 	}
+	vdbe_field_ref_create(field_ref, space->def->field_count);
 	vdbe_field_ref_prepare_tuple(field_ref, new_tuple);
 
 	struct ck_constraint *ck_constraint;
diff --git a/src/box/sql.c b/src/box/sql.c
index da9ecea80a4dd3b52c0f812068061e0fa46d792a..7202c258752f93a747ecfa718445fdfe7971344a 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1361,16 +1361,16 @@ sql_template_space_new(Parse *parser, const char *name)
 }
 
 /**
- * Initialize a new vdbe_field_ref instance with given tuple
- * data.
+ * Fill vdbe_field_ref instance with given tuple data.
+ *
  * @param field_ref The vdbe_field_ref instance to initialize.
  * @param tuple The tuple object pointer or NULL when undefined.
  * @param data The tuple data (is always defined).
  * @param data_sz The size of tuple data (is always defined).
  */
 static void
-vdbe_field_ref_create(struct vdbe_field_ref *field_ref, struct tuple *tuple,
-		      const char *data, uint32_t data_sz)
+vdbe_field_ref_fill(struct vdbe_field_ref *field_ref, struct tuple *tuple,
+		    const char *data, uint32_t data_sz)
 {
 	field_ref->tuple = tuple;
 	field_ref->data = data;
@@ -1379,13 +1379,7 @@ vdbe_field_ref_create(struct vdbe_field_ref *field_ref, struct tuple *tuple,
 	const char *field0 = data;
 	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->field_count = MIN(field_ref->field_capacity, 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]));
@@ -1397,15 +1391,22 @@ void
 vdbe_field_ref_prepare_data(struct vdbe_field_ref *field_ref, const char *data,
 			    uint32_t data_sz)
 {
-	vdbe_field_ref_create(field_ref, NULL, data, data_sz);
+	vdbe_field_ref_fill(field_ref, NULL, data, data_sz);
 }
 
 void
 vdbe_field_ref_prepare_tuple(struct vdbe_field_ref *field_ref,
 			     struct tuple *tuple)
 {
-	vdbe_field_ref_create(field_ref, tuple, tuple_data(tuple),
-			      tuple_bsize(tuple));
+	vdbe_field_ref_fill(field_ref, tuple, tuple_data(tuple),
+			    tuple_bsize(tuple));
+}
+
+void
+vdbe_field_ref_create(struct vdbe_field_ref *ref, uint32_t capacity)
+{
+	memset(ref, 0, sizeof(*ref) + capacity * sizeof(ref->slots[0]));
+	ref->field_capacity = capacity;
 }
 
 ssize_t
diff --git a/src/box/sql.h b/src/box/sql.h
index dc40c32e365940e7ecb62a96e5ef1bcf2d55c04a..18611c52e261eb5b659c933cd69f338c61c407c3 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -376,6 +376,8 @@ struct vdbe_field_ref {
 	uint32_t data_sz;
 	/** Count of fields in tuple. */
 	uint32_t field_count;
+	/** Number of allocated slots. */
+	uint32_t field_capacity;
 	/** Format that match data in field data. */
 	struct tuple_format *format;
 	/**
@@ -394,8 +396,8 @@ struct vdbe_field_ref {
 };
 
 /**
- * Initialize a new vdbe_field_ref instance with given tuple
- * data.
+ * Fill vdbe_field_ref instance with given tuple data.
+ *
  * @param field_ref The vdbe_field_ref instance to initialize.
  * @param data The tuple data.
  * @param data_sz The size of tuple data.
@@ -405,8 +407,8 @@ vdbe_field_ref_prepare_data(struct vdbe_field_ref *field_ref, const char *data,
 			    uint32_t data_sz);
 
 /**
- * Initialize a new vdbe_field_ref instance with given tuple
- * data.
+ * Fill vdbe_field_ref instance with given tuple data.
+ *
  * @param field_ref The vdbe_field_ref instance to initialize.
  * @param tuple The tuple object pointer.
  */
@@ -414,6 +416,10 @@ void
 vdbe_field_ref_prepare_tuple(struct vdbe_field_ref *field_ref,
 			     struct tuple *tuple);
 
+/** Initialize a new vdbe_field_ref instance. */
+void
+vdbe_field_ref_create(struct vdbe_field_ref *ref, uint32_t capacity);
+
 #if defined(__cplusplus)
 } /* extern "C" { */
 #endif
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index a6a01487932ab717f3735076d71509c9869c5f98..e7079fafb95739577aee5790a9b6fc405dbf7b42 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -2443,6 +2443,7 @@ func_sql_expr_call(struct func *func, struct port *args, struct port *ret)
 	struct vdbe_field_ref *ref;
 	size_t size = sizeof(ref->slots[0]) * count + sizeof(*ref);
 	ref = region_aligned_alloc(region, size, alignof(*ref));
+	vdbe_field_ref_create(ref, count);
 	vdbe_field_ref_prepare_data(ref, data, mp_size);
 	ref->format = format;
 	if (sql_bind_ptr(stmt, 1, ref) != 0)
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 29a8be783449a88c7a5d7b851503ab6ce4668d99..15ed3acce72e9dd3683e60eaca6fea5d1e797edf 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -206,6 +206,7 @@ allocateCursor(
 		memset(pCx, 0, offsetof(VdbeCursor,uc));
 		pCx->eCurType = eCurType;
 		pCx->nField = nField;
+		vdbe_field_ref_create(&pCx->field_ref, nField);
 		if (eCurType==CURTYPE_TARANTOOL) {
 			pCx->uc.pCursor = (BtCursor*)&pMem->z[bt_offset];
 			sqlCursorZero(pCx->uc.pCursor);
diff --git a/test/sql-luatest/gh_5310_cursor_invalidation_test.lua b/test/sql-luatest/gh_5310_cursor_invalidation_test.lua
index 508249ad9469e56dbb7d028266e67369136d6de4..496f05b920f2da7c8c85b0cdb61ee3d3400ceb5e 100644
--- a/test/sql-luatest/gh_5310_cursor_invalidation_test.lua
+++ b/test/sql-luatest/gh_5310_cursor_invalidation_test.lua
@@ -11,7 +11,8 @@ g.after_all(function()
     g.server:stop()
 end)
 
-g.test_cursor_invalidation = function()
+-- Make sure that tuples with undescribed fields do not cause an error.
+g.test_cursor_invalidation_1 = function()
     g.server:exec(function()
         local t = require('luatest')
         local s = box.schema.space.create('T', {format = {'A'}})
@@ -22,3 +23,19 @@ g.test_cursor_invalidation = function()
         s:drop()
     end)
 end
+
+--
+-- Make sure that tuples with fields described in tuple format but not described
+-- in space format do not cause an error.
+--
+g.test_cursor_invalidation_2 = function()
+    g.server:exec(function()
+        local t = require('luatest')
+        local s = box.schema.space.create('T', {format = {{'A', 'integer'}}})
+        s:create_index('ii', {parts = {{1, 'integer'}, {2, 'integer'},
+                                       {3, 'integer'}, {4, 'integer'}}})
+        s:insert({1,2,3,4})
+        t.assert_equals(box.execute([[SELECT * FROM t;]]).rows, {{1}})
+        s:drop()
+    end)
+end