[clang] f84f17c - [-Wunsafe-buffer-usage] Add an unsafe gadget for pointer-arithmetic operations
Ziqing Luo via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 4 17:02:05 PST 2023
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() {
More information about the cfe-commits
mailing list