[Tarantool-patches] [PATCH] lua/merger: fix NULL dereferences on error paths

Alexander Turenko alexander.turenko at tarantool.org
Tue Nov 10 11:13:14 MSK 2020


There are two situations that may lead to a NULL dereference.

First, when an attempt to create a merge source is failed. Now only OOM
may trigger this code path. Reproducing it in a test is tricky, so I
left it without a test case.

Second, when an attempt to create a merger is failed. The reason of the
fail may be a 'wrong' key_def: when we unable to create a tuple format
from it. Say, when the key_def defines several key parts using the same
field, but marks them with different field types.

Fixes #5450
---

https://github.com/tarantool/tarantool/issues/5450
Totktonada/gh-5450-merger-segfault-on-wrong-key-def
https://github.com/tarantool/tarantool/tree/Totktonada/gh-5450-merger-segfault-on-wrong-key-def

CI is not sufficient now, because of [1]. Aside
engine/errinj_ddl.test.lua, all tests are passed on my Linux machine.

[1]: https://github.com/tarantool/tarantool/issues/5473

 src/box/lua/merger.c                          |  8 ++----
 .../gh-5450-merger-wrong-key-def.test.lua     | 26 +++++++++++++++++++
 2 files changed, 28 insertions(+), 6 deletions(-)
 create mode 100755 test/box-tap/gh-5450-merger-wrong-key-def.test.lua

diff --git a/src/box/lua/merger.c b/src/box/lua/merger.c
index 17e237902..89bdfffa6 100644
--- a/src/box/lua/merger.c
+++ b/src/box/lua/merger.c
@@ -266,10 +266,8 @@ lbox_merge_source_new(struct lua_State *L, const char *func_name,
 		lua_pushnil(L);
 
 	struct merge_source *source = luaL_merge_source_new(L);
-	if (source == NULL) {
-		merge_source_unref(source);
+	if (source == NULL)
 		return luaT_error(L);
-	}
 	*(struct merge_source **)
 		luaL_pushcdata(L, CTID_STRUCT_MERGE_SOURCE_REF) = source;
 	lua_pushcfunction(L, lbox_merge_source_gc);
@@ -387,10 +385,8 @@ lbox_merger_new(struct lua_State *L)
 	struct merge_source *merger = merger_new(key_def, sources, source_count,
 						 reverse);
 	free(sources);
-	if (merger == NULL) {
-		merge_source_unref(merger);
+	if (merger == NULL)
 		return luaT_error(L);
-	}
 
 	*(struct merge_source **)
 		luaL_pushcdata(L, CTID_STRUCT_MERGE_SOURCE_REF) = merger;
diff --git a/test/box-tap/gh-5450-merger-wrong-key-def.test.lua b/test/box-tap/gh-5450-merger-wrong-key-def.test.lua
new file mode 100755
index 000000000..033f42da4
--- /dev/null
+++ b/test/box-tap/gh-5450-merger-wrong-key-def.test.lua
@@ -0,0 +1,26 @@
+#!/usr/bin/env tarantool
+
+local tap = require('tap')
+local key_def_lib = require('key_def')
+local merger = require('merger')
+
+local test = tap.test('gh-5450-merger-wrong-key-def')
+test:plan(1)
+
+-- gh-5450: creating of merger leads to segfault, when passed
+-- key_def is not usable to create a tuple format.
+local key_def = key_def_lib.new({
+    {fieldno = 6, type = 'string'},
+    {fieldno = 6, type = 'unsigned'},
+})
+local exp_err = "Field 6 has type 'string' in one index, but type " ..
+                "'unsigned' in another"
+-- At the moment of writting the test, it is sufficient to pass an
+-- empty sources table to trigger the attempt to create a tuple
+-- format.
+local sources = {}
+local ok, err = pcall(merger.new, key_def, sources)
+test:is_deeply({ok, tostring(err)}, {false, exp_err},
+               'unable to create a tuple format')
+
+os.exit(test:check() and 0 or 1)
-- 
2.25.0



More information about the Tarantool-patches mailing list