Fix use-after-free bug in Tooling.

Summary:
`buildASTFromCodeWithArgs()` was creating a memory buffer referencing a
stack-allocated string.  This diff changes the implementation to copy the code
string into the memory buffer so that said buffer owns the memory.

Patch by Yitzhak Mandelbaum.

Reviewers: alexfh

Reviewed By: alexfh

Subscribers: cfe-commits, EricWF

Differential Revision: https://reviews.llvm.org/D55765

llvm-svn: 350638
This commit is contained in:
Alexander Kornienko 2019-01-08 16:55:13 +00:00
parent 0d99031de0
commit 973fcc25fb
3 changed files with 14 additions and 17 deletions

View File

@ -205,7 +205,7 @@ bool runToolOnCodeWithArgs(
///
/// \return The resulting AST or null if an error occurred.
std::unique_ptr<ASTUnit>
buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc",
buildASTFromCode(StringRef Code, StringRef FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
@ -223,10 +223,10 @@ buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc",
///
/// \return The resulting AST or null if an error occurred.
std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
const Twine &Code, const std::vector<std::string> &Args,
const Twine &FileName = "input.cc", const Twine &ToolName = "clang-tool",
StringRef Code, const std::vector<std::string> &Args,
StringRef FileName = "input.cc", StringRef ToolName = "clang-tool",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>(),
std::make_shared<PCHContainerOperations>(),
ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster());
/// Utility to run a FrontendAction in a single clang invocation.

View File

@ -574,20 +574,16 @@ namespace clang {
namespace tooling {
std::unique_ptr<ASTUnit>
buildASTFromCode(const Twine &Code, const Twine &FileName,
buildASTFromCode(StringRef Code, StringRef FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName,
"clang-tool", std::move(PCHContainerOps));
}
std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
const Twine &Code, const std::vector<std::string> &Args,
const Twine &FileName, const Twine &ToolName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
StringRef Code, const std::vector<std::string> &Args, StringRef FileName,
StringRef ToolName, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArgumentsAdjuster Adjuster) {
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
@ -599,13 +595,11 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
new FileManager(FileSystemOptions(), OverlayFileSystem));
ToolInvocation Invocation(
getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef),
getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName),
&Action, Files.get(), std::move(PCHContainerOps));
SmallString<1024> CodeStorage;
InMemoryFileSystem->addFile(FileNameRef, 0,
llvm::MemoryBuffer::getMemBuffer(
Code.toNullTerminatedStringRef(CodeStorage)));
InMemoryFileSystem->addFile(FileName, 0,
llvm::MemoryBuffer::getMemBufferCopy(Code));
if (!Invocation.run())
return nullptr;

View File

@ -11,6 +11,7 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <cctype>
@ -32,7 +33,9 @@ using StmtMatcher = internal::Matcher<Stmt>;
std::unique_ptr<ASTUnit>
buildASTFromCodeWithArgs(const Twine &Code,
const std::vector<std::string> &Args) {
auto AST = tooling::buildASTFromCodeWithArgs(Code, Args);
SmallString<1024> CodeStorage;
auto AST =
tooling::buildASTFromCodeWithArgs(Code.toStringRef(CodeStorage), Args);
EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred());
return AST;
}