Make FileEntry::getName() valid across calls to FileManager::getFile()

Because we may change the name of a FileEntry inside getFile, the name
returned by FileEntry::getName() could be destroyed.  This was causing a
use-after-free when searching the HeaderFileInfo on-disk hashtable for a
module or pch.

llvm-svn: 217385
This commit is contained in:
Ben Langmuir
2014-09-08 16:15:54 +00:00
parent dfa274eb58
commit ab86fbe425
2 changed files with 17 additions and 4 deletions

View File

@@ -270,6 +270,19 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
FileEntry &UFE = UniqueRealFiles[Data.UniqueID];
NamedFileEnt.setValue(&UFE);
// If the name returned by getStatValue is different than Filename, re-intern
// the name.
if (Data.Name != Filename) {
auto &NamedFileEnt = SeenFileEntries.GetOrCreateValue(Data.Name);
if (!NamedFileEnt.getValue())
NamedFileEnt.setValue(&UFE);
else
assert(NamedFileEnt.getValue() == &UFE &&
"filename from getStatValue() refers to wrong file");
InterndFileName = NamedFileEnt.getKeyData();
}
if (UFE.isValid()) { // Already have an entry with this inode, return it.
// FIXME: this hack ensures that if we look up a file by a virtual path in
@@ -286,13 +299,13 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// to switch towards a design where we return a FileName object that
// encapsulates both the name by which the file was accessed and the
// corresponding FileEntry.
UFE.Name = Data.Name;
UFE.Name = InterndFileName;
return &UFE;
}
// Otherwise, we don't have this file yet, add it.
UFE.Name = Data.Name;
UFE.Name = InterndFileName;
UFE.Size = Data.Size;
UFE.ModTime = Data.ModTime;
UFE.Dir = DirInfo;