Skip to content

Commit 42ae055

Browse files
committed
[NFC] Fix potential for use-after-free in DumpModuleInfoAction
Since each `DumpModuleInfoAction` can now contain a pointer to a `raw_ostream`, saving there a poiter that owned by a local `unique_ptr` may cause use-after-free. Clarify ownership and save a `shared_ptr` inside of `DumpModuleInfoAction` instead. Found by static analyzer. Reviewed By: tahonermann, aaron.ballman Differential Revision: https://reviews.llvm.org/D146412
1 parent efd34ba commit 42ae055

File tree

3 files changed

+11
-8
lines changed

3 files changed

+11
-8
lines changed

clang/include/clang/Frontend/FrontendActions.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,8 @@ class SyntaxOnlyAction : public ASTFrontendAction {
177177
/// Dump information about the given module file, to be used for
178178
/// basic debugging and discovery.
179179
class DumpModuleInfoAction : public ASTFrontendAction {
180-
public:
181180
// Allow other tools (ex lldb) to direct output for their use.
182-
llvm::raw_ostream *OutputStream = nullptr;
181+
std::shared_ptr<llvm::raw_ostream> OutputStream;
183182

184183
protected:
185184
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
@@ -188,6 +187,9 @@ class DumpModuleInfoAction : public ASTFrontendAction {
188187
void ExecuteAction() override;
189188

190189
public:
190+
DumpModuleInfoAction() = default;
191+
explicit DumpModuleInfoAction(std::shared_ptr<llvm::raw_ostream> Out)
192+
: OutputStream(Out) {}
191193
bool hasPCHSupport() const override { return false; }
192194
bool hasASTFileSupport() const override { return true; }
193195
bool hasIRSupport() const override { return false; }

clang/lib/Frontend/FrontendActions.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -780,14 +780,12 @@ static StringRef ModuleKindName(Module::ModuleKind MK) {
780780
void DumpModuleInfoAction::ExecuteAction() {
781781
assert(isCurrentFileAST() && "dumping non-AST?");
782782
// Set up the output file.
783-
std::unique_ptr<llvm::raw_fd_ostream> OutFile;
784783
CompilerInstance &CI = getCompilerInstance();
785784
StringRef OutputFileName = CI.getFrontendOpts().OutputFile;
786785
if (!OutputFileName.empty() && OutputFileName != "-") {
787786
std::error_code EC;
788-
OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC,
789-
llvm::sys::fs::OF_TextWithCRLF));
790-
OutputStream = OutFile.get();
787+
OutputStream.reset(new llvm::raw_fd_ostream(
788+
OutputFileName.str(), EC, llvm::sys::fs::OF_TextWithCRLF));
791789
}
792790
llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs();
793791

lldb/source/Commands/CommandObjectTarget.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,8 +2179,11 @@ class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed {
21792179
const char *clang_args[] = {"clang", pcm_path};
21802180
compiler.setInvocation(clang::createInvocation(clang_args));
21812181

2182-
clang::DumpModuleInfoAction dump_module_info;
2183-
dump_module_info.OutputStream = &result.GetOutputStream().AsRawOstream();
2182+
// Pass empty deleter to not attempt to free memory that was allocated
2183+
// outside of the current scope, possibly statically.
2184+
std::shared_ptr<llvm::raw_ostream> Out(
2185+
&result.GetOutputStream().AsRawOstream(), [](llvm::raw_ostream *) {});
2186+
clang::DumpModuleInfoAction dump_module_info(Out);
21842187
// DumpModuleInfoAction requires ObjectFilePCHContainerReader.
21852188
compiler.getPCHContainerOperations()->registerReader(
21862189
std::make_unique<clang::ObjectFilePCHContainerReader>());

0 commit comments

Comments
 (0)