Skip to content

Commit 61746b3

Browse files
authored
[ClangImporter] Stop abusing a Clang API to avoid a use-after-free. (#11377)
In order to allow LLDB to debug an app as it was written (in theory), we stuff a semi-preprocessed version of the bridging header into the generated swiftmodule file, so that we can fall back on it if the original bridging header is deleted. The specific functionality we want is in Clang's -rewrite-includes option, but we need to write to an in-memory buffer instead of a file. The existing code took the meat of clang::RewriteIncludesAction and recreated it manually. We got away with this in the past, but upstream Clang has changed how clang::RewriteIncludesAction works, and now what we were doing before results in the (unused) file output stream being deallocated before the (also unused) buffering stream wrapped around it. Rather than continue trying to half-use an existing Clang FrontendAction, just make a new one that does the thing we want and nothing else. I'd like to revisit this whole idea in the future -- it doesn't actually preserve debuggability in the case where the bridging header may have changed, because we don't check for modifications in all the things it includes. But for now this should preserve the existing functionality. rdar://problem/33693128
1 parent 326756d commit 61746b3

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,13 +1289,23 @@ std::string ClangImporter::getBridgingHeaderContents(StringRef headerPath,
12891289

12901290
std::string result;
12911291
bool success = llvm::CrashRecoveryContext().RunSafelyOnThread([&] {
1292-
clang::RewriteIncludesAction action;
1293-
action.BeginSourceFile(rewriteInstance,
1294-
invocation->getFrontendOpts().Inputs.front());
1292+
// A much simpler version of clang::RewriteIncludesAction that lets us
1293+
// write to an in-memory buffer.
1294+
class RewriteIncludesAction : public clang::PreprocessorFrontendAction {
1295+
raw_ostream &OS;
1296+
1297+
void ExecuteAction() override {
1298+
clang::CompilerInstance &compiler = getCompilerInstance();
1299+
clang::RewriteIncludesInInput(compiler.getPreprocessor(), &OS,
1300+
compiler.getPreprocessorOutputOpts());
1301+
}
1302+
public:
1303+
explicit RewriteIncludesAction(raw_ostream &os) : OS(os) {}
1304+
};
1305+
12951306
llvm::raw_string_ostream os(result);
1296-
clang::RewriteIncludesInInput(rewriteInstance.getPreprocessor(), &os,
1297-
rewriteInstance.getPreprocessorOutputOpts());
1298-
action.EndSourceFile();
1307+
RewriteIncludesAction action(os);
1308+
rewriteInstance.ExecuteAction(action);
12991309
});
13001310

13011311
success |= !rewriteInstance.getDiagnostics().hasErrorOccurred();

0 commit comments

Comments
 (0)