lua/merger: fix use-after-free during iteration
All merge sources (including the merger itself) share the same `<merge source>:pairs()` implementation, which returns `gen, param, state` triplet. `gen` is `lbox_merge_source_gen()`, `param` is `nil`, `state` in the merge source. The `lbox_merge_source_gen()` returns `source, tuple`. The returned source is supposed to be the same object as a one passed to the function (`gen(param, state)`), so the function assumes the object as alive and don't increment source's refcounter at entering, don't decrease it at exitting. This logic is perfect, but there was a mistake in the implementation: the function returns a new cdata object (which holds the same pointer to the merge source structure) instead of the same cdata object. The new cdata object neither increases the source's refcounter at pushing to Lua, nor decreases it at collecting. At result, if we'll loss the original merge source object (and the first `state` that is returned from `:pairs()`), the source structure may be freed. The pointer in the new cdata object will be invalid so. A sketchy code that illustrates the problem: ```lua gen, param, state0 = source:pairs() assert(state0 == source) source = nil state1, tuple = gen(param, state0) state0 = nil -- assert(state1 == source) -- would fails collectgarbage() -- The cdata object that is referenced as `source` and as `state` -- is collected. The GC handler is called and dropped the merge -- source structure refcounter to zero. The structure is freed. -- The call below will crash. gen(param, state1) ``` In the fixed code `state1 == source`, so the GC handler is not called prematurely: we have the merge source object alive till the end of the iterator or till the stop of the traversal. Fixes #7657 NO_DOC=a crash is definitely not what we want to document (cherry picked from commit 3bc64229)
Showing
- changelogs/unreleased/merger-use-after-free-in-gen.md 4 additions, 0 deletionschangelogs/unreleased/merger-use-after-free-in-gen.md
- src/box/lua/merger.c 27 additions, 4 deletionssrc/box/lua/merger.c
- test/box-luatest/gh_7657_merger_use_after_free_in_gen_test.lua 126 additions, 0 deletions...box-luatest/gh_7657_merger_use_after_free_in_gen_test.lua
Loading
Please register or sign in to comment