From fd11b390f3ea0223d272b71bde67b3727ccf1cd5 Mon Sep 17 00:00:00 2001 From: Axel Naumann <Axel.Naumann@cern.ch> Date: Sat, 23 Jun 2018 11:12:19 +0200 Subject: [PATCH] [cling] Only check pointers for Decls from writable dirs (ROOT-9377). --- .../NullDerefProtectionTransformer.cpp | 42 ++++++++++++++++++- .../NullDerefProtectionTransformer.h | 10 +++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp index 22257513699..0305f37ac67 100644 --- a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp +++ b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp @@ -18,15 +18,17 @@ #include "clang/AST/Expr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Sema/Lookup.h" #include <bitset> -#include <map> using namespace clang; namespace { +using namespace cling; + class PointerCheckInjector : public RecursiveASTVisitor<PointerCheckInjector> { private: Interpreter& m_Interp; @@ -226,9 +228,45 @@ namespace cling { NullDerefProtectionTransformer::~NullDerefProtectionTransformer() { } + bool NullDerefProtectionTransformer::shouldTransform(const clang::Decl* D) { + if (D->isFromASTFile()) + return false; + if (D->isTemplateDecl()) + return false; + + auto Loc = D->getLocation(); + if (Loc.isInvalid()) + return false; + + SourceManager& SM = m_Interp->getSema().getSourceManager(); + auto FID = SM.getFileID(Loc); + if (FID.isInvalid()) + return false; + + auto FE = SM.getFileEntryForID(FID); + if (!FE) + return false; + + auto Dir = FE->getDir(); + if (!Dir) + return false; + + auto IterAndInserted = m_ShouldVisitDir.try_emplace(Dir, true); + if (IterAndInserted.second == false) + return IterAndInserted.first->second; + + if (llvm::sys::fs::can_write(Dir->getName())) + return true; // `true` is already emplaced above. + + // Remember that this dir is not writable and should not be visited. + IterAndInserted.first->second = false; + return false; + } + + ASTTransformer::Result NullDerefProtectionTransformer::Transform(clang::Decl* D) { - if (getCompilationOpts().CheckPointerValidity) { + if (getCompilationOpts().CheckPointerValidity && shouldTransform(D)) { PointerCheckInjector injector(*m_Interp); injector.TraverseDecl(D); } diff --git a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h index a7b679fe9fc..72fd608869e 100644 --- a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h +++ b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h @@ -13,8 +13,11 @@ #include "ASTTransformer.h" +#include "llvm/ADT/DenseMap.h" + namespace clang { class Decl; + class DirectoryEntry; } namespace cling { class Interpreter; @@ -24,6 +27,13 @@ namespace cling { class NullDerefProtectionTransformer : public ASTTransformer { cling::Interpreter* m_Interp; + + /// Whether to visit a Decl coming from a file in a given directory. + llvm::DenseMap<const clang::DirectoryEntry*, bool> m_ShouldVisitDir; + + /// Whether the declaration should be visited and possibly transformed. + bool shouldTransform(const clang::Decl* D); + public: ///\ brief Constructs the NullDeref AST Transformer. /// -- GitLab