[clang] 88f7f01 - [-Wunsafe-buffer-usage] Match unsafe pointers being casted to bool or participating in pointer subtractions
Ziqing Luo via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 11 15:10:35 PDT 2023
Author: Ziqing Luo
Date: 2023-04-11T15:09:51-07:00
New Revision: 88f7f018e23b24d3c31dd2b4f3cd68481d1739c1
URL: https://github.com/llvm/llvm-project/commit/88f7f018e23b24d3c31dd2b4f3cd68481d1739c1
DIFF: https://github.com/llvm/llvm-project/commit/88f7f018e23b24d3c31dd2b4f3cd68481d1739c1.diff
LOG: [-Wunsafe-buffer-usage] Match unsafe pointers being casted to bool or participating in pointer subtractions
Add two new unique cases to the Unspecified Pointer Context (UPC),
under which we match unsafe operation patterns:
- A pointer being casted to a boolean value is in a UPC;
- A pointer participating in pointer subtraction is in a UPC.
Reviewed by: NoQ (Artem Dergachev), malavikasamak (Malavika Samak)
Differential revision: https://reviews.llvm.org/D144064
Added:
Modified:
clang/lib/Analysis/UnsafeBufferUsage.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp
Removed:
################################################################################
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index fdc7584ad6ff1..6a597c8851002 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -163,24 +163,40 @@ static internal::Matcher<Stmt>
isInUnspecifiedPointerContext(internal::Matcher<Stmt> InnerMatcher) {
// 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
+ // attribute), or
+ // 2. the operand of a pointer-to-(integer or bool) cast operation; or
// 3. the operand of a comparator operation; or
+ // 4. the operand of a pointer subtraction operation
+ // (i.e., computing the distance between two pointers); or ...
+
auto CallArgMatcher =
callExpr(forEachArgumentWithParam(InnerMatcher,
hasPointerType() /* array also decays to pointer type*/),
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)));
auto CompOperandMatcher =
binaryOperator(hasAnyOperatorName("!=", "==", "<", "<=", ">", ">="),
eachOf(hasLHS(allOf(hasPointerType(), InnerMatcher)),
hasRHS(allOf(hasPointerType(), InnerMatcher))));
- return stmt(anyOf(CallArgMatcher, CastOperandMatcher, CompOperandMatcher));
+ // 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)));
+
+ 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.)
}
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp
index 8fdbc4bed4f6d..474e7495e3e1d 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-addressof-arraysubscript.cpp
@@ -13,12 +13,30 @@ void address_to_integer(int x) {
// 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];
f((unsigned long) &p[5], &p[x]);
- // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:21-[[@LINE-1]]:26}:"&p.data()[5]"
- // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:28-[[@LINE-2]]:33}:"&p.data()[x]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:21-[[@LINE-1]]:26}:"&p.data()[5]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:28-[[@LINE-2]]:33}:"&p.data()[x]"
}
void ignore_unsafe_calls(int x) {
@@ -55,9 +73,26 @@ void index_is_zero() {
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:10}:"p.data()"
}
-// CHECK-NOT: fix-it
+void pointer_subtraction(int x) {
+ int * p = new int[10];
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
+
+ int n = &p[9] - &p[4];
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"&p.data()[9]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:24}:"&p.data()[4]"
+ if (&p[9] - &p[x]) {
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:12}:"&p.data()[9]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:20}:"&p.data()[x]"
+ return;
+ }
+}
+
// To test multiple function declarations, each of which carries
-//
diff erent incomplete informations:
+//
diff erent incomplete informations.
+// no fix-it in the rest of this test:
+
[[clang::unsafe_buffer_usage]]
void unsafe_g(void*);
@@ -65,8 +100,9 @@ void unsafe_g(void*);
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*);
@@ -78,6 +114,7 @@ void unsafe_h(void* p) { ((char*)p)[10]; }
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]]
}
More information about the cfe-commits
mailing list