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]] } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits