From cbe2ff451c5c637ec8bd39d30f65ae5f47888b32 Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov@tarantool.org>
Date: Mon, 27 Feb 2023 14:42:32 +0300
Subject: [PATCH] vinyl: fix use after free on key alloc error in iterator
 constructor

Error labes got mixed up. Fix the order and add a test.

Fixes commit 3f0263395bee ("vinyl: implement iterator pagination").

Closes #8372

NO_DOC=bug fix
NO_CHANGELOG=fix for unreleased feature

(cherry picked from commit 074e4eb8531ff48b0fa040f1f9a1cfffa3e0a869)
---
 src/box/vinyl.c                               |  4 +-
 ...8372_key_alloc_error_in_iter_ctor_test.lua | 38 +++++++++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)
 create mode 100644 test/vinyl-luatest/gh_8372_key_alloc_error_in_iter_ctor_test.lua

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index fa8e0cd110..62d8992568 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -3832,10 +3832,10 @@ vinyl_index_create_iterator(struct index *base, enum iterator_type type,
 		&it->iterator, lsm, tx, type, it->key, last,
 		(const struct vy_read_view **)&tx->read_view);
 	return (struct iterator *)it;
-err_key:
-	mempool_free(&env->iterator_pool, it);
 err_pos:
 	tuple_unref(it->key.stmt);
+err_key:
+	mempool_free(&env->iterator_pool, it);
 	return NULL;
 }
 
diff --git a/test/vinyl-luatest/gh_8372_key_alloc_error_in_iter_ctor_test.lua b/test/vinyl-luatest/gh_8372_key_alloc_error_in_iter_ctor_test.lua
new file mode 100644
index 0000000000..6942cfcc1d
--- /dev/null
+++ b/test/vinyl-luatest/gh_8372_key_alloc_error_in_iter_ctor_test.lua
@@ -0,0 +1,38 @@
+local server = require('luatest.server')
+local t = require('luatest')
+
+local g = t.group()
+
+g.before_all(function(cg)
+    cg.server = server:new({alias = 'master'})
+    cg.server:start()
+    cg.server:exec(function()
+        box.schema.create_space('test', {engine = 'vinyl'})
+        box.space.test:create_index('primary', {parts = {1, 'string'}})
+    end)
+end)
+
+g.after_all(function(cg)
+    cg.server:drop()
+end)
+
+g.test_key_alloc_error = function(cg)
+    cg.server:exec(function()
+        box.cfg({vinyl_max_tuple_size = 1})
+        t.assert_error_msg_matches(
+            "Failed to allocate [%d]+ bytes for tuple: tuple is too large. " ..
+            "Check 'vinyl_max_tuple_size' configuration option.",
+            box.space.test.select, box.space.test, {'foo'})
+    end)
+end
+
+g.test_pos_alloc_error = function(cg)
+    cg.server:exec(function()
+        box.cfg({vinyl_max_tuple_size = 100})
+        t.assert_error_msg_matches(
+            "Failed to allocate [%d]+ bytes for tuple: tuple is too large. " ..
+            "Check 'vinyl_max_tuple_size' configuration option.",
+            box.space.test.select, box.space.test, {},
+            {after = {string.rep('x', 101)}})
+    end)
+end
-- 
GitLab