llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Malavika Samak (malavikasamak)

<details>
<summary>Changes</summary>

Do not warn when a constant sized array is indexed with an expression that 
contains bitwise and operation
involving constants and it always results in a bound safe access.

(rdar://136684050)

---
Full diff: https://github.com/llvm/llvm-project/pull/112284.diff


2 Files Affected:

- (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+45) 
- (modified) clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp (+14) 


``````````diff
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 97f1c4f16b8f4c..cdfdcc17536391 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -427,6 +427,45 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
   //    -  e. g. "Try harder to find a NamedDecl to point at in the note."
   //    already duplicated
   //  - call both from Sema and from here
+  std::function<bool(const Expr *exp, const ConstantArrayType *CATy,
+                     unsigned int limit)>
+      SafeMaskedAccess;
+  unsigned int RecLimit = 5;
+  llvm::APInt Max;
+  bool Initialized = false;
+
+  SafeMaskedAccess = [&](const Expr *exp, const ConstantArrayType *CATy,
+                         unsigned int RecLimit) -> bool {
+    if (RecLimit == 0)
+      return false;
+
+    RecLimit--;
+
+    if (const auto *IntLit = dyn_cast<IntegerLiteral>(exp)) {
+      const APInt ArrIdx = IntLit->getValue();
+      if (ArrIdx.isNonNegative() &&
+          ArrIdx.getLimitedValue() < CATy->getLimitedSize())
+        return true;
+      if (!Initialized) {
+        Max = ArrIdx;
+        Initialized = true;
+      } else {
+        Max = Max & ArrIdx.getLimitedValue();
+      }
+      if (Max.getLimitedValue() < CATy->getLimitedSize())
+        return true;
+    }
+
+    if (const auto *BinEx = dyn_cast<BinaryOperator>(exp)) {
+      if (SafeMaskedAccess(BinEx->getLHS()->IgnoreParenCasts(), CATy, 
RecLimit))
+        return true;
+      else if (SafeMaskedAccess(BinEx->getRHS()->IgnoreParenCasts(), CATy,
+                                RecLimit))
+        return true;
+    }
+
+    return false;
+  };
 
   const auto *BaseDRE =
       dyn_cast<DeclRefExpr>(Node.getBase()->IgnoreParenImpCasts());
@@ -446,6 +485,12 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
     if (ArrIdx.isNonNegative() &&
         ArrIdx.getLimitedValue() < CATy->getLimitedSize())
       return true;
+  } else if (const auto *BinEx = dyn_cast<BinaryOperator>(Node.getIdx())) {
+    if (BinEx->getOpcode() != BO_And)
+      return false;
+
+    Max.setAllBits();
+    return SafeMaskedAccess(Node.getIdx(), CATy, RecLimit);
   }
 
   return false;
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
index 8b2f103ec66708..e5a5ca57f66883 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
@@ -33,6 +33,20 @@ void constant_idx_safe0(unsigned idx) {
   buffer[0] = 0;
 }
 
+int array[10]; // expected-warning{{'array' is an unsafe buffer that does not 
perform bounds checks}}
+
+void masked_idx(unsigned long long idx) {
+  array[idx & 5] = 10; // no warning
+  array[idx & 11 & 5] = 3; // no warning
+  array[idx & 11] = 20; // expected-note{{used in buffer access here}} 
+}
+
+int array2[5];
+
+void mased_idx_false() {
+  array2[6 & 5];
+}
+
 void constant_idx_unsafe(unsigned idx) {
   int buffer[10];       // expected-warning{{'buffer' is an unsafe buffer that 
does not perform bounds checks}}
                         // expected-note@-1{{change type of 'buffer' to 
'std::array' to label it for hardening}}

``````````

</details>


https://github.com/llvm/llvm-project/pull/112284
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to