[clang] While refactoring projects to eradicate unsafe buffer accesses using … (PR #75650)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff ec92d74a0ef89b9dd46aee6ec8aca6bfd3c66a54 809bf6f4237f634feaeb7e5b0b88be3a2e4de455 -- clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h clang/lib/Analysis/UnsafeBufferUsage.cpp clang/lib/Sema/AnalysisBasedWarnings.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e4eca9939b..4e1c76c300 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -729,7 +729,7 @@ class DataInvocationGadget : public WarningGadget { constexpr static const char *const OpTag = "data_invocation_expr"; const ExplicitCastExpr *Op; - public: +public: DataInvocationGadget(const MatchFinder::MatchResult ) : WarningGadget(Kind::DataInvocation), Op(Result.Nodes.getNodeAs(OpTag)) {} @@ -737,12 +737,12 @@ class DataInvocationGadget : public WarningGadget { static bool classof(const Gadget *G) { return G->getKind() == Kind::DataInvocation; } - + static Matcher matcher() { -return stmt( -explicitCastExpr(has(cxxMemberCallExpr(callee( - cxxMethodDecl(hasName("data")).bind(OpTag)); - } +return stmt(explicitCastExpr(has(cxxMemberCallExpr( + callee(cxxMethodDecl(hasName("data")) +.bind(OpTag)); + } const Stmt *getBaseStmt() const override { return Op; } DeclUseList getClaimedVarUseSites() const override { return {}; } @@ -2684,7 +2684,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D, // every problematic operation and consider it done. No need to deal // with fixable gadgets, no need to group operations by variable. for (const auto : WarningGadgets) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false, + Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false, D->getASTContext()); } @@ -2920,8 +2920,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, Tracker, Handler, VarGrpMgr); for (const auto : UnsafeOps.noVar) { -Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false - , D->getASTContext()); +Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false, + D->getASTContext()); } for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar) { @@ -2932,8 +2932,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, : FixItList{}, D); for (const auto : WarningGadgets) { - Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/true -, D->getASTContext()); + Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/true, +D->getASTContext()); } } } diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 4f8e181806..bcf3241514 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2226,7 +2226,7 @@ public: UnsafeBufferUsageReporter(Sema , bool SuggestSuggestions) : S(S), SuggestSuggestions(SuggestSuggestions) {} - void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl, + void handleUnsafeOperation(const Stmt *Operation, bool IsRelatedToDecl, ASTContext ) override { SourceLocation Loc; SourceRange Range; @@ -2263,19 +2263,21 @@ public: MsgParam = 3; } else if (const auto *ECE = dyn_cast(Operation)) { QualType destType = ECE->getType(); -const uint64_t dSize = Ctx.getTypeSize(destType.getTypePtr()->getPointeeType()); -if(const auto *CE =dyn_cast(ECE->getSubExpr())) { +const uint64_t dSize = +Ctx.getTypeSize(destType.getTypePtr()->getPointeeType()); +if (const auto *CE = dyn_cast(ECE->getSubExpr())) { + + if (CE->getRecordDecl()->getQualifiedNameAsString().compare( + "std::span")) +return; - if(CE->getRecordDecl()->getQualifiedNameAsString().compare("std::span")) - return; - QualType srcType = CE->getType(); - const uint64_t sSize = Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType()); - if(sSize >= dSize) + const uint64_t sSize = + Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType()); + if (sSize >= dSize) return;
[clang] While refactoring projects to eradicate unsafe buffer accesses using … (PR #75650)
llvmbot wrote: @llvm/pr-subscribers-clang-analysis @llvm/pr-subscribers-clang Author: Malavika Samak (malavikasamak) Changes …-Wunsafe-buffer-usage, there maybe accidental re-introduction of new OutOfBound accesses into the code bases. One such case is invoking span::data() method on a span variable to retrieve a pointer, which is then cast to a larger type and dereferenced. Such dereferences can introduce OutOfBound accesses. To address this, a new WarningGadget is being introduced to warn against such invocations. --- Full diff: https://github.com/llvm/llvm-project/pull/75650.diff 6 Files Affected: - (modified) clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h (+1-1) - (modified) clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def (+1) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1-1) - (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+33-4) - (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+17-2) - (added) clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp (+133) ``diff diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 8a2d56668e32f9..b28f2c6b99c50e 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -66,7 +66,7 @@ class UnsafeBufferUsageHandler { /// Invoked when an unsafe operation over raw pointers is found. virtual void handleUnsafeOperation(const Stmt *Operation, - bool IsRelatedToDecl) = 0; + bool IsRelatedToDecl, ASTContext ) = 0; /// Invoked when a fix is suggested against a variable. This function groups /// all variables that must be fixed together (i.e their types must be changed diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index 757ee452ced748..c9766168836510 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -30,6 +30,7 @@ WARNING_GADGET(Decrement) WARNING_GADGET(ArraySubscript) WARNING_GADGET(PointerArithmetic) WARNING_GADGET(UnsafeBufferUsageAttr) +WARNING_GADGET(DataInvocation) FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context FIXABLE_GADGET(DerefSimplePtrArithFixable) FIXABLE_GADGET(PointerDereference) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 94e97a891baedc..9038dd879f54ae 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12058,7 +12058,7 @@ def warn_unsafe_buffer_variable : Warning< InGroup, DefaultIgnore; def warn_unsafe_buffer_operation : Warning< "%select{unsafe pointer operation|unsafe pointer arithmetic|" - "unsafe buffer access|function introduces unsafe buffer manipulation}0">, + "unsafe buffer access|function introduces unsafe buffer manipulation|unsafe invocation of span::data}0">, InGroup, DefaultIgnore; def note_unsafe_buffer_operation : Note< "used%select{| in pointer arithmetic| in buffer access}0 here">; diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 70eec1cee57f8e..e4eca9939b10d5 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -721,6 +721,33 @@ class UnsafeBufferUsageAttrGadget : public WarningGadget { DeclUseList getClaimedVarUseSites() const override { return {}; } }; +// Warning gadget for unsafe invocation of span::data method. +// Triggers when the pointer returned by the invocation is immediately +// cast to a larger type. + +class DataInvocationGadget : public WarningGadget { + constexpr static const char *const OpTag = "data_invocation_expr"; + const ExplicitCastExpr *Op; + + public: + DataInvocationGadget(const MatchFinder::MatchResult ) + : WarningGadget(Kind::DataInvocation), +Op(Result.Nodes.getNodeAs(OpTag)) {} + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::DataInvocation; + } + + static Matcher matcher() { +return stmt( +explicitCastExpr(has(cxxMemberCallExpr(callee( + cxxMethodDecl(hasName("data")).bind(OpTag)); + } + const Stmt *getBaseStmt() const override { return Op; } + + DeclUseList getClaimedVarUseSites() const override { return {}; } +}; + // Represents expressions of the form `DRE[*]` in the Unspecified Lvalue // Context (see `isInUnspecifiedLvalueContext`). // Note here `[]` is the built-in subscript operator. @@ -2657,8 +2684,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D, // every problematic operation and consider it done. No need to deal
[clang] While refactoring projects to eradicate unsafe buffer accesses using … (PR #75650)
https://github.com/malavikasamak created https://github.com/llvm/llvm-project/pull/75650 …-Wunsafe-buffer-usage, there maybe accidental re-introduction of new OutOfBound accesses into the code bases. One such case is invoking span::data() method on a span variable to retrieve a pointer, which is then cast to a larger type and dereferenced. Such dereferences can introduce OutOfBound accesses. To address this, a new WarningGadget is being introduced to warn against such invocations. >From 809bf6f4237f634feaeb7e5b0b88be3a2e4de455 Mon Sep 17 00:00:00 2001 From: MalavikaSamak Date: Fri, 15 Dec 2023 11:40:55 -0800 Subject: [PATCH] While refactoring projects to eradicate unsafe buffer accesses using -Wunsafe-buffer-usage, there maybe accidental re-introduction of new OutOfBound accesses into the code bases. One such case is invoking span::data() method on a span variable to retrieve a pointer, which is then cast to a larger type and dereferenced. Such dereferences can introduce OutOfBound accesses. To address this, a new WarningGadget is being introduced to warn against such invocations. --- .../Analysis/Analyses/UnsafeBufferUsage.h | 2 +- .../Analyses/UnsafeBufferUsageGadgets.def | 1 + .../clang/Basic/DiagnosticSemaKinds.td| 2 +- clang/lib/Analysis/UnsafeBufferUsage.cpp | 37 - clang/lib/Sema/AnalysisBasedWarnings.cpp | 19 ++- ...e-buffer-usage-warning-data-invocation.cpp | 133 ++ 6 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 8a2d56668e32f9..b28f2c6b99c50e 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -66,7 +66,7 @@ class UnsafeBufferUsageHandler { /// Invoked when an unsafe operation over raw pointers is found. virtual void handleUnsafeOperation(const Stmt *Operation, - bool IsRelatedToDecl) = 0; + bool IsRelatedToDecl, ASTContext ) = 0; /// Invoked when a fix is suggested against a variable. This function groups /// all variables that must be fixed together (i.e their types must be changed diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index 757ee452ced748..c9766168836510 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -30,6 +30,7 @@ WARNING_GADGET(Decrement) WARNING_GADGET(ArraySubscript) WARNING_GADGET(PointerArithmetic) WARNING_GADGET(UnsafeBufferUsageAttr) +WARNING_GADGET(DataInvocation) FIXABLE_GADGET(ULCArraySubscript) // `DRE[any]` in an Unspecified Lvalue Context FIXABLE_GADGET(DerefSimplePtrArithFixable) FIXABLE_GADGET(PointerDereference) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 94e97a891baedc..9038dd879f54ae 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12058,7 +12058,7 @@ def warn_unsafe_buffer_variable : Warning< InGroup, DefaultIgnore; def warn_unsafe_buffer_operation : Warning< "%select{unsafe pointer operation|unsafe pointer arithmetic|" - "unsafe buffer access|function introduces unsafe buffer manipulation}0">, + "unsafe buffer access|function introduces unsafe buffer manipulation|unsafe invocation of span::data}0">, InGroup, DefaultIgnore; def note_unsafe_buffer_operation : Note< "used%select{| in pointer arithmetic| in buffer access}0 here">; diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 70eec1cee57f8e..e4eca9939b10d5 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -721,6 +721,33 @@ class UnsafeBufferUsageAttrGadget : public WarningGadget { DeclUseList getClaimedVarUseSites() const override { return {}; } }; +// Warning gadget for unsafe invocation of span::data method. +// Triggers when the pointer returned by the invocation is immediately +// cast to a larger type. + +class DataInvocationGadget : public WarningGadget { + constexpr static const char *const OpTag = "data_invocation_expr"; + const ExplicitCastExpr *Op; + + public: + DataInvocationGadget(const MatchFinder::MatchResult ) + : WarningGadget(Kind::DataInvocation), +Op(Result.Nodes.getNodeAs(OpTag)) {} + + static bool classof(const Gadget *G) { +return G->getKind() == Kind::DataInvocation; + } + + static Matcher matcher() { +return stmt( +explicitCastExpr(has(cxxMemberCallExpr(callee( +