[clang] While refactoring projects to eradicate unsafe buffer accesses using … (PR #75650)

2023-12-15 Thread via cfe-commits

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)

2023-12-15 Thread via cfe-commits

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)

2023-12-15 Thread Malavika Samak via cfe-commits

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(
+