ziqingluo-90 created this revision.
ziqingluo-90 added reviewers: jkorous, NoQ, malavikasamak, t-rasmud.
Herald added a project: All.
ziqingluo-90 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

To add two new unique cases to the Unspecified Pointer Context (UPC):

- A pointer being casted to a boolean value is in a UPC;
- A pointer participating in pointer subtraction is in a UPC.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144064

Files:
  clang/lib/Analysis/UnsafeBufferUsage.cpp
  
clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp
===================================================================
--- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp
@@ -13,6 +13,24 @@
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:37-[[@LINE-1]]:42}:"(p.data() + x)"
 }
 
+void address_to_bool(int x) {
+  int * p = new int[10];
+  bool a = (bool) &p[5];
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:24}:"(p.data() + 5)"
+  bool b = (bool) &p[x];
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:24}:"(p.data() + x)"
+
+  bool a1 = &p[5];
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:18}:"(p.data() + 5)"
+  bool b1 = &p[x];
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:18}:"(p.data() + x)"
+
+  if (&p[5]) {
+    // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:12}:"(p.data() + 5)"
+    return;
+  }
+}
+
 void call_argument(int x) {
   int * p = new int[10];
 
@@ -31,9 +49,9 @@
 	   &p[x]);
 
   int * q = new int[10];
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> q"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> q"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
   unsafe_f((unsigned long) &q[5],
 	   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:28-[[@LINE-1]]:33}:"(q.data() + 5)"
 	   (void*)0);
@@ -45,8 +63,29 @@
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:37-[[@LINE-1]]:42}:"(p.data() + 5)"
 }
 
+
+void pointer_subtraction(int x) {
+  int * p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
+
+  int n = &p[9] - &p[4];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"(p.data() + 9)"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:24}:"(p.data() + 4)"
+  if (&p[9] - &p[x]) {
+    // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:12}:"(p.data() + 9)"
+    // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:20}:"(p.data() + x)"
+    return;
+  }
+}
+
+
 // To test multiple function declarations, each of which carries
-// different incomplete informations:
+// different incomplete informations.
+// no fix-it in the rest of this test:
+
+// CHECK-NOT: fix-it:"{{.*}}":{
 [[clang::unsafe_buffer_usage]]
 void unsafe_g(void*);
 
@@ -54,9 +93,7 @@
 
 void multiple_unsafe_fundecls() {
   int * p = new int[10];
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
   unsafe_g(&p[5]);
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
 }
 
 void unsafe_h(void*);
@@ -68,7 +105,5 @@
 
 void multiple_unsafe_fundecls2() {
   int * p = new int[10];
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
   unsafe_h(&p[5]);
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
 }
Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===================================================================
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -152,7 +152,9 @@
   // A UPC can be
   // 1. an argument of a function call (except the callee has [[unsafe_...]]
   // attribute), or
-  // 2. the operand of a cast operation; or
+  // 2. the operand of a cast-to-(Integer or Boolean) operation; or
+  // 3. the operand of a pointer subtraction operation; or
+  // 4. the operand of a pointer comparison operation; or
   // ...
   auto CallArgMatcher =
       callExpr(forEachArgumentWithParam(InnerMatcher,
@@ -160,15 +162,27 @@
           unless(callee(functionDecl(hasAttr(attr::UnsafeBufferUsage)))));
 
   auto CastOperandMatcher =
-      explicitCastExpr(hasCastKind(CastKind::CK_PointerToIntegral),
-                       castSubExpr(allOf(hasPointerType(), InnerMatcher)));
+    castExpr(anyOf(hasCastKind(CastKind::CK_PointerToIntegral),
+		   hasCastKind(CastKind::CK_PointerToBoolean)),
+	     castSubExpr(allOf(hasPointerType(), InnerMatcher)));
+
+  // A matcher that matches pointer subtractions:
+  auto PtrSubtractionMatcher =
+    binaryOperator(hasOperatorName("-"),
+		   // Note that here we need both LHS and RHS to be
+		   // pointer. Then the inner matcher can match any of
+		   // them:
+		   allOf(hasLHS(hasPointerType()),
+			 hasRHS(hasPointerType())),
+		   eachOf(hasLHS(InnerMatcher),
+			  hasRHS(InnerMatcher)));
 
   auto CompOperandMatcher =
     binaryOperator(hasAnyOperatorName("!=", "==", "<", "<=", ">", ">="),
 		   eachOf(hasLHS(allOf(hasPointerType(), InnerMatcher)),
 			  hasRHS(allOf(hasPointerType(), InnerMatcher))));
-  
-  return stmt(anyOf(CallArgMatcher, CastOperandMatcher, CompOperandMatcher));  
+
+  return stmt(anyOf(CallArgMatcher, CastOperandMatcher, CompOperandMatcher, PtrSubtractionMatcher));
   // FIXME: any more cases? (UPC excludes the RHS of an assignment.  For now we
   // don't have to check that.)
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to