Skip to content

Commit bffd3ca

Browse files
committed
[Serialization] Store the path inside ModuleSearchPath as a string, not a StringRef
The idea behind storing a StringRef was to reduce the memory footprint because we made the assumption that a `ModuleSearchPath` always outlives the `SearchPathOptions` it was created from. What I did not consider was that the path was referencing into a `std::vector`, which could get resized, thus invaliding the memory the `ModuleSearchPath`’s `StringRef` was pointing to, causing memory corruption. To fix this, store the path string inisde the `ModuleSearchPath` itself. Since we store a `ModuleSearchPath` for every file inside that module search path in the `LookupTable`, by itself this would cause a new copy of the path to be stored for every file inside a module search path. To avoid this, make `ModuleSearchPath` ref counted and only store a reference to one shared `ModuleSearchPath` entry in the lookup table. rdar://88888679
1 parent 91e8c92 commit bffd3ca

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

include/swift/AST/SearchPathOptions.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ enum class ModuleSearchPathKind {
3636

3737
/// A single module search path that can come from different sources, e.g.
3838
/// framework search paths, import search path etc.
39-
class ModuleSearchPath {
40-
/// The actual path of the module search path. References a search path string
41-
/// stored inside \c SearchPathOptions, which must outlive this reference.
42-
StringRef Path;
39+
class ModuleSearchPath : public llvm::RefCountedBase<ModuleSearchPath> {
40+
/// The actual path of the module search path.
41+
std::string Path;
4342

4443
/// The kind of the search path.
4544
ModuleSearchPathKind Kind;
@@ -73,6 +72,8 @@ class ModuleSearchPath {
7372
}
7473
};
7574

75+
using ModuleSearchPathPtr = llvm::IntrusiveRefCntPtr<ModuleSearchPath>;
76+
7677
class SearchPathOptions;
7778

7879
/// Maintains a mapping of filenames to search paths that contain a file with
@@ -109,7 +110,7 @@ class ModuleSearchPathLookup {
109110
const SearchPathOptions *Opts;
110111
} State;
111112

112-
llvm::StringMap<SmallVector<ModuleSearchPath, 4>> LookupTable;
113+
llvm::StringMap<SmallVector<ModuleSearchPathPtr, 4>> LookupTable;
113114

114115
/// Scan the directory at \p SearchPath for files and add those files to the
115116
/// lookup table. \p Kind specifies the search path kind and \p Index the

lib/AST/SearchPathOptions.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,24 @@ void ModuleSearchPathLookup::addFilesInPathToLookupTable(
1919
llvm::vfs::FileSystem *FS, StringRef SearchPath, ModuleSearchPathKind Kind,
2020
bool IsSystem, unsigned SearchPathIndex) {
2121
std::error_code Error;
22-
assert(llvm::all_of(
23-
LookupTable,
24-
[&](const auto &LookupTableEntry) {
25-
return llvm::none_of(
26-
LookupTableEntry.second,
27-
[&](const ModuleSearchPath &ExistingSearchPath) -> bool {
28-
return ExistingSearchPath.getKind() == Kind &&
29-
ExistingSearchPath.getIndex() == SearchPathIndex;
30-
});
31-
}) &&
22+
auto entryAlreadyExists = [this](ModuleSearchPathKind Kind,
23+
unsigned SearchPathIndex) -> bool {
24+
return llvm::any_of(LookupTable, [&](const auto &LookupTableEntry) {
25+
return llvm::any_of(
26+
LookupTableEntry.second, [&](ModuleSearchPathPtr ExistingSearchPath) {
27+
return ExistingSearchPath->getKind() == Kind &&
28+
ExistingSearchPath->getIndex() == SearchPathIndex;
29+
});
30+
});
31+
};
32+
assert(!entryAlreadyExists(Kind, SearchPathIndex) &&
3233
"Search path with this kind and index already exists");
34+
ModuleSearchPathPtr TableEntry =
35+
new ModuleSearchPath(SearchPath, Kind, IsSystem, SearchPathIndex);
3336
for (auto Dir = FS->dir_begin(SearchPath, Error);
3437
!Error && Dir != llvm::vfs::directory_iterator(); Dir.increment(Error)) {
3538
StringRef Filename = llvm::sys::path::filename(Dir->path());
36-
LookupTable[Filename].emplace_back(SearchPath, Kind, IsSystem,
37-
SearchPathIndex);
39+
LookupTable[Filename].push_back(TableEntry);
3840
}
3941
}
4042

@@ -98,9 +100,9 @@ ModuleSearchPathLookup::searchPathsContainingFile(
98100

99101
for (auto &Filename : Filenames) {
100102
for (auto &Entry : LookupTable[Filename]) {
101-
if (ResultIds.insert(std::make_pair(Entry.getKind(), Entry.getIndex()))
103+
if (ResultIds.insert(std::make_pair(Entry->getKind(), Entry->getIndex()))
102104
.second) {
103-
Result.push_back(&Entry);
105+
Result.push_back(Entry.get());
104106
}
105107
}
106108
}

0 commit comments

Comments
 (0)