From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH] vinyl: fix crash if iterator is used throughout DDL Date: Thu, 14 Feb 2019 16:18:25 +0300 Message-Id: <882b7f20bb0dbc7310dd95eee28af583b88c1413.1550150143.git.vdavydov.dev@gmail.com> To: kostja@tarantool.org Cc: tarantool-patches@freelists.org List-ID: vy_run_iterator doesn't take a reference to the format it uses to decode statements loaded from disk. As a result, the format may be deleted by DDL, leading to a use-after-free bug. Fix this by taking a reference to the format used by an iterator. Closes #4000 --- https://github.com/tarantool/tarantool/issues/4000 https://github.com/tarantool/tarantool/commits/dv/gh-4000-vy-fix-iterator-crash-on-ddl src/box/vy_run.c | 7 +++++++ test/vinyl/errinj_ddl.result | 44 ++++++++++++++++++++++++++++++++++++++++++ test/vinyl/errinj_ddl.test.lua | 20 +++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/box/vy_run.c b/src/box/vy_run.c index 581f8cb0..9be89357 100644 --- a/src/box/vy_run.c +++ b/src/box/vy_run.c @@ -1436,6 +1436,12 @@ vy_run_iterator_open(struct vy_run_iterator *itr, itr->search_started = false; itr->search_ended = false; + + /* + * Make sure the format we use to create tuples won't + * go away if DDL is called while the iterator is used. + */ + tuple_format_ref(format); } /** @@ -1602,6 +1608,7 @@ void vy_run_iterator_close(struct vy_run_iterator *itr) { vy_run_iterator_stop(itr); + tuple_format_unref(itr->format); TRASH(itr); } diff --git a/test/vinyl/errinj_ddl.result b/test/vinyl/errinj_ddl.result index 4f5d59cd..932132db 100644 --- a/test/vinyl/errinj_ddl.result +++ b/test/vinyl/errinj_ddl.result @@ -593,3 +593,47 @@ s:select() s:drop() --- ... +-- +-- gh-4000: index iterator crashes if used throughout DDL. +-- +s = box.schema.space.create('test', {engine = 'vinyl'}) +--- +... +_ = s:create_index('pk') +--- +... +_ = s:create_index('sk', {parts = {2, 'unsigned'}}) +--- +... +s:replace{1, 1} +--- +- [1, 1] +... +box.snapshot() +--- +- ok +... +errinj.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 0.01) +--- +- ok +... +c = fiber.channel(1) +--- +... +_ = fiber.create(function() c:put(s.index.sk:select()) end) +--- +... +s.index.sk:alter{parts = {2, 'number'}} +--- +... +errinj.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 0) +--- +- ok +... +c:get() +--- +- - [1, 1] +... +s:drop() +--- +... diff --git a/test/vinyl/errinj_ddl.test.lua b/test/vinyl/errinj_ddl.test.lua index 0948bc3d..95e0ad3c 100644 --- a/test/vinyl/errinj_ddl.test.lua +++ b/test/vinyl/errinj_ddl.test.lua @@ -258,3 +258,23 @@ fiber.sleep(0) s:create_index('sk', {parts = {2, 'unsigned'}}) s:select() s:drop() + +-- +-- gh-4000: index iterator crashes if used throughout DDL. +-- +s = box.schema.space.create('test', {engine = 'vinyl'}) +_ = s:create_index('pk') +_ = s:create_index('sk', {parts = {2, 'unsigned'}}) + +s:replace{1, 1} +box.snapshot() + +errinj.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 0.01) +c = fiber.channel(1) +_ = fiber.create(function() c:put(s.index.sk:select()) end) +s.index.sk:alter{parts = {2, 'number'}} +errinj.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 0) + +c:get() + +s:drop() -- 2.11.0