diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index d3c3dfe1fa3be..47753a7efdbbd 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -19,6 +19,7 @@ #include "clang/AST/Stmt.h" #include "clang/Basic/SourceLocation.h" #include "llvm/Support/Debug.h" +#include namespace clang { @@ -203,6 +204,8 @@ namespace internal { bool anyConflict(const llvm::SmallVectorImpl &FixIts, const SourceManager &SM); } // namespace internal + +std::set findUnsafePointers(const FunctionDecl *FD); } // end namespace clang #endif /* LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H */ diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index cee11ca563dea..9a9b9e4c26234 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1957,6 +1957,8 @@ class WarningGadget : public Gadget { virtual void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler, bool IsRelatedToDecl, ASTContext &Ctx) const = 0; + + virtual SmallVector getUnsafePtrs() const = 0; }; /// Fixable gadgets correspond to code patterns that aren't always unsafe but @@ -2039,6 +2041,10 @@ class IncrementGadget : public WarningGadget { return std::move(Uses); } + + SmallVector getUnsafePtrs() const override { + return {Op->getSubExpr()->IgnoreParenImpCasts()}; + } }; /// A decrement of a pointer-type value is unsafe as it may run the pointer @@ -2082,6 +2088,10 @@ class DecrementGadget : public WarningGadget { return {}; } + + SmallVector getUnsafePtrs() const override { + return {Op->getSubExpr()->IgnoreParenImpCasts()}; + } }; /// Array subscript expressions on raw pointers as if they're arrays. Unsafe as @@ -2131,6 +2141,10 @@ class ArraySubscriptGadget : public WarningGadget { return {}; } + + SmallVector getUnsafePtrs() const override { + return {ASE->getBase()->IgnoreParenImpCasts()}; + } }; /// A pointer arithmetic expression of one of the forms: @@ -2194,6 +2208,11 @@ class PointerArithmeticGadget : public WarningGadget { return {}; } + + SmallVector getUnsafePtrs() const override { + return {Ptr->IgnoreParenImpCasts()}; + } + // FIXME: pointer adding zero should be fine // FIXME: this gadge will need a fix-it }; @@ -2251,6 +2270,8 @@ class SpanTwoParamConstructorGadget : public WarningGadget { } return {}; } + + SmallVector getUnsafePtrs() const override { return {}; } }; /// A pointer initialization expression of the form: @@ -2483,6 +2504,8 @@ class UnsafeBufferUsageAttrGadget : public WarningGadget { SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { return {}; } + + SmallVector getUnsafePtrs() const override { return {}; } }; /// A call of a constructor that performs unchecked buffer operations @@ -2521,6 +2544,8 @@ class UnsafeBufferUsageCtorAttrGadget : public WarningGadget { SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); } DeclUseList getClaimedVarUseSites() const override { return {}; } + + SmallVector getUnsafePtrs() const override { return {}; } }; // Warning gadget for unsafe invocation of span::data method. @@ -2587,6 +2612,8 @@ class DataInvocationGadget : public WarningGadget { return true; return false; } + + SmallVector getUnsafePtrs() const override { return {}; } }; class UnsafeLibcFunctionCallGadget : public WarningGadget { @@ -2714,6 +2741,8 @@ class UnsafeLibcFunctionCallGadget : public WarningGadget { } DeclUseList getClaimedVarUseSites() const override { return {}; } + + SmallVector getUnsafePtrs() const override { return {}; } }; // Represents expressions of the form `DRE[*]` in the Unspecified Lvalue @@ -3216,6 +3245,10 @@ class CountAttributedPointerArgumentGadget : public WarningGadget { } return {}; } + + SmallVector getUnsafePtrs() const override { + return {}; + } }; // Represents an argument that is being passed to a __single pointer. @@ -3266,6 +3299,10 @@ class SinglePointerArgumentGadget : public WarningGadget { } return {}; } + + SmallVector getUnsafePtrs() const override { + return {}; + } }; /// Scan the function and return a list of gadgets found with provided kits. @@ -3395,6 +3432,52 @@ template struct CompareNode { } }; +std::set clang::findUnsafePointers(const FunctionDecl *FD) { + class MockReporter : public UnsafeBufferUsageHandler { + public: + MockReporter() {} + void handleUnsafeOperation(const Stmt *, bool, ASTContext &) override {} + void handleUnsafeLibcCall(const CallExpr *, unsigned, ASTContext &, + const Expr *UnsafeArg = nullptr) override {} + void handleUnsafeOperationInContainer(const Stmt *, bool, + ASTContext &) override {} + void handleUnsafeVariableGroup(const VarDecl *, + const VariableGroupsManager &, FixItList &&, + const Decl *, + const FixitStrategy &) override {} + bool isSafeBufferOptOut(const SourceLocation &) const override { + return false; + } + bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override { + return false; + } + bool ignoreUnsafeBufferInLibcCall(const SourceLocation &) const override { + return false; + } + std::string getUnsafeBufferUsageAttributeTextAt( + SourceLocation, StringRef WSSuffix = "") const override { + return ""; + } + }; + + FixableGadgetList FixableGadgets; + WarningGadgetList WarningGadgets; + DeclUseTracker Tracker; + MockReporter IgnoreHandler; + + findGadgets(FD->getBody(), FD->getASTContext(), IgnoreHandler, false, + FixableGadgets, WarningGadgets, Tracker); + + std::set Result; + for (auto &G : WarningGadgets) { + for (const Expr *E : G->getUnsafePtrs()) { + Result.insert(E); + } + } + + return Result; +} + struct WarningGadgetSets { std::map, // To keep keys sorted by their locations in the map so that the