Author: Ziqing Luo Date: 2023-01-04T16:50:21-08:00 New Revision: f84f17c489f7cb84d72e84a6b1b6c54bd8d52717
URL: https://github.com/llvm/llvm-project/commit/f84f17c489f7cb84d72e84a6b1b6c54bd8d52717 DIFF: https://github.com/llvm/llvm-project/commit/f84f17c489f7cb84d72e84a6b1b6c54bd8d52717.diff LOG: [-Wunsafe-buffer-usage] Add an unsafe gadget for pointer-arithmetic operations For -Wunsafe-buffer-usage diagnostics, we want to warn about pointer arithmetics since resulting pointers can be used to access buffers. Therefore, I add an `UnsafeGadget` representing general pointer arithmetic operations. Reviewed by: NoQ Differential revision: https://reviews.llvm.org/D139233 Added: Modified: clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def clang/lib/Analysis/UnsafeBufferUsage.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index fc8800fed3953..f24e925966094 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -28,6 +28,7 @@ UNSAFE_GADGET(Increment) UNSAFE_GADGET(Decrement) UNSAFE_GADGET(ArraySubscript) +UNSAFE_GADGET(PointerArithmetic) #undef SAFE_GADGET #undef UNSAFE_GADGET diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 6a8e38297ebe2..29c8dbb45fe9f 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -304,6 +304,55 @@ class ArraySubscriptGadget : public UnsafeGadget { return {}; } }; + +/// A pointer arithmetic expression of one of the forms: +/// \code +/// ptr + n | n + ptr | ptr - n | ptr += n | ptr -= n +/// \endcode +class PointerArithmeticGadget : public UnsafeGadget { + static constexpr const char *const PointerArithmeticTag = "ptrAdd"; + static constexpr const char *const PointerArithmeticPointerTag = "ptrAddPtr"; + const BinaryOperator *PA; // pointer arithmetic expression + const Expr * Ptr; // the pointer expression in `PA` + +public: + PointerArithmeticGadget(const MatchFinder::MatchResult &Result) + : UnsafeGadget(Kind::PointerArithmetic), + PA(Result.Nodes.getNodeAs<BinaryOperator>(PointerArithmeticTag)), + Ptr(Result.Nodes.getNodeAs<Expr>(PointerArithmeticPointerTag)) {} + + static bool classof(const Gadget *G) { + return G->getKind() == Kind::PointerArithmetic; + } + + static Matcher matcher() { + auto HasIntegerType = anyOf( + hasType(isInteger()), hasType(enumType())); + auto PtrAtRight = allOf(hasOperatorName("+"), + hasRHS(expr(hasPointerType()).bind(PointerArithmeticPointerTag)), + hasLHS(HasIntegerType)); + auto PtrAtLeft = allOf( + anyOf(hasOperatorName("+"), hasOperatorName("-"), + hasOperatorName("+="), hasOperatorName("-=")), + hasLHS(expr(hasPointerType()).bind(PointerArithmeticPointerTag)), + hasRHS(HasIntegerType)); + + return stmt(binaryOperator(anyOf(PtrAtLeft, PtrAtRight)).bind(PointerArithmeticTag)); + } + + const Stmt *getBaseStmt() const override { return PA; } + + DeclUseList getClaimedVarUseSites() const override { + if (const auto *DRE = + dyn_cast<DeclRefExpr>(Ptr->IgnoreParenImpCasts())) { + return {DRE}; + } + + return {}; + } + // FIXME: pointer adding zero should be fine + //FIXME: this gadge will need a fix-it +}; } // namespace namespace { diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp index b367bd2c781ce..476ec73c4f744 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp @@ -169,10 +169,36 @@ template<typename T, int N> T f(T t, T * pt, T a[N], T (&b)[N]) { return &t[1]; // expected-warning{{unchecked operation on raw buffer in expression}} } +// Testing pointer arithmetic for pointer-to-int, qualified multi-level +// pointer, pointer to a template type, and auto type +T_ptr_t getPtr(); + +template<typename T> +void testPointerArithmetic(int * p, const int **q, T * x) { + int a[10]; + auto y = &a[0]; + + foo(p + 1, 1 + p, p - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} + *q + 1, 1 + *q, *q - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} + x + 1, 1 + x, x - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} + y + 1, 1 + y, y - 1, // expected-warning3{{unchecked operation on raw buffer in expression}} + getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unchecked operation on raw buffer in expression}} + ); + + p += 1; p -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} + *q += 1; *q -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} + y += 1; y -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} + x += 1; x -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}} +} + void testTemplate(int * p) { int *a[10]; foo(f(p, &p, a, a)[1]); // expected-warning{{unchecked operation on raw buffer in expression}}, \ expected-note{{in instantiation of function template specialization 'f<int *, 10>' requested here}} + + const int **q = const_cast<const int **>(&p); + + testPointerArithmetic(p, q, p); //expected-note{{in instantiation of function template specialization 'testPointerArithmetic<int>' requested here}} } void testPointerToMember() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits