Repository navigation
memenv: register the FileState created by NewAppendableFile - #1351
Open
xhon-pelushi wants to merge 1 commit into
Open
xhon-pelushi wants to merge 1 commit into
xhon-pelushi wants to merge 1 commit into
Conversation
NewAppendableFile() takes a reference to the map slot, and when the file does
not exist yet it creates a FileState and Refs it -- but never stores it back
into the slot. The slot was default-constructed to nullptr by operator[], so
the name stays mapped to a null FileState while FileExists() reports it as
present.
Every later use of that name dereferences the null pointer. The shortest path
to a crash does not even need a second lookup, because ~InMemoryEnv() Unrefs
every value in the map:
Env* env = NewMemEnv(Env::Default());
WritableFile* file;
env->NewAppendableFile("/dir/f", &file);
delete file;
delete env; // SEGV in FileState::Unref()
Under ASan that reports as "SEGV on unknown address 0x000000000010 ... READ
memory access" in ___pthread_mutex_lock, reached from FileState::Unref() at
memenv.cc:44 via ~InMemoryEnv() at memenv.cc:227 - 0x10 being the offset of
the mutex inside FileState, read through a null this.
The Ref() also leaked, since nothing owned that reference: WritableFileImpl
takes its own in the constructor and drops it in the destructor.
Store the new FileState in the slot, matching NewWritableFile(), which already
does file_map_[fname] = file for the same case. The existing coverage missed
this because MemEnvTest.Basics only calls NewAppendableFile() on a file that
NewWritableFile() has already created, which takes the other branch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1328.
InMemoryEnv::NewAppendableFile()takes a reference to the map slot and, when the file does not exist yet, creates aFileStateandRef()s it — but never stores it back:operator[]has already inserted the key, so the name stays mapped tonullptrwhileFileExists()reports it as present.It crashes sooner than the issue suggests
The report describes later lookups dereferencing the null. No second lookup is needed, because
~InMemoryEnv()unrefs every value in the map (memenv.cc:227):Under ASan:
0x10is the offset of the mutex insideFileState, read through a nullthis.The
Ref()also leaked:WritableFileImpltakes and drops its own reference in its constructor/destructor, so nothing owned the one created here.Fix
One line —
*sptr = file;— which makes the appendable path matchNewWritableFile()a few lines above, which already doesfile_map_[fname] = file;for exactly this case.Why this was not already caught
MemEnvTest.BasicscallsNewAppendableFile("/dir/f", …)only afterNewWritableFile()has created that same file, so it always takes thefile != nullptrbranch. The new-file branch had no coverage.The added test appends to a fresh name, checks the size, reopens for append to confirm it extends rather than replaces, and reads the contents back.
Testing
MemEnvTest.AppendableFileRegistersNewFileMemEnvTest.*ctest(Debug)leveldb_testsunder ASanThe 2 skips are the compression tests, which need snappy/zstd.