[clang-tools-extra] [clang-tidy] Add new `bugprone-suspicious-pointer-arithmetics-using-sizeof` (`cert-arr39-c`) check (PR #106061)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 27 07:30:10 PDT 2024
https://github.com/whisperity updated https://github.com/llvm/llvm-project/pull/106061
>From 0202caa773928bfc395b850f52191ab15afe0eb4 Mon Sep 17 00:00:00 2001
From: zporky <zporky at gmail.com>
Date: Thu, 26 Oct 2023 20:40:39 +0200
Subject: [PATCH 01/19] Initial pointer arithmetics using sizeof matcher
---
.../bugprone/BugproneTidyModule.cpp | 3 ++
.../clang-tidy/bugprone/CMakeLists.txt | 1 +
...iousPointerArithmeticsUsingSizeofCheck.cpp | 36 +++++++++++++++++++
...iciousPointerArithmeticsUsingSizeofCheck.h | 30 ++++++++++++++++
.../clang-tidy/cert/CERTTidyModule.cpp | 4 +++
5 files changed, 74 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 543c522899d7a5..4f74fd9fd50543 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -67,6 +67,7 @@
#include "SuspiciousMemoryComparisonCheck.h"
#include "SuspiciousMemsetUsageCheck.h"
#include "SuspiciousMissingCommaCheck.h"
+#include "SuspiciousPointerArithmeticsUsingSizeofCheck.h"
#include "SuspiciousReallocUsageCheck.h"
#include "SuspiciousSemicolonCheck.h"
#include "SuspiciousStringCompareCheck.h"
@@ -204,6 +205,8 @@ class BugproneModule : public ClangTidyModule {
"bugprone-suspicious-memset-usage");
CheckFactories.registerCheck<SuspiciousMissingCommaCheck>(
"bugprone-suspicious-missing-comma");
+ CheckFactories.registerCheck<SuspiciousPointerArithmeticsUsingSizeofCheck>(
+ "bugprone-suspicious-pointer-arithmetics-using-sizeof");
CheckFactories.registerCheck<SuspiciousReallocUsageCheck>(
"bugprone-suspicious-realloc-usage");
CheckFactories.registerCheck<SuspiciousSemicolonCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index 0df9e439b715e5..c9877e6f5a7ddc 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -64,6 +64,7 @@ add_clang_library(clangTidyBugproneModule
SuspiciousMemoryComparisonCheck.cpp
SuspiciousMemsetUsageCheck.cpp
SuspiciousMissingCommaCheck.cpp
+ SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
SuspiciousReallocUsageCheck.cpp
SuspiciousSemicolonCheck.cpp
SuspiciousStringCompareCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
new file mode 100644
index 00000000000000..abfa1bc7f037ea
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -0,0 +1,36 @@
+//===--- SuspiciousPointerArithmeticsUsingSizeofCheck.cpp - clang-tidy --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuspiciousPointerArithmeticsUsingSizeofCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+SuspiciousPointerArithmeticsUsingSizeofCheck::SuspiciousPointerArithmeticsUsingSizeofCheck(
+ StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {
+}
+
+void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ sizeOfExpr(expr())
+ .bind("sizeof-expression"),
+ this);
+}
+
+void SuspiciousPointerArithmeticsUsingSizeofCheck::check(
+ const MatchFinder::MatchResult &Result) {
+}
+
+} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
new file mode 100644
index 00000000000000..d39e15f0ccc3a0
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
@@ -0,0 +1,30 @@
+//===--- SuspiciousPointerArithmeticsUsingSizeofCheck.h - clang-tidy -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSSIZEOFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSSIZEOFCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// Find suspicious calls to string compare functions.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-sizeof.html
+class SuspiciousPointerArithmeticsUsingSizeofCheck : public ClangTidyCheck {
+public:
+ SuspiciousPointerArithmeticsUsingSizeofCheck(StringRef Name, ClangTidyContext *Context);
+// void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSSIZEOFCHECK_H
diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
index d448d9ba614548..17a7e4bc51049d 100644
--- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -15,6 +15,7 @@
#include "../bugprone/SignedCharMisuseCheck.h"
#include "../bugprone/SpuriouslyWakeUpFunctionsCheck.h"
#include "../bugprone/SuspiciousMemoryComparisonCheck.h"
+#include "../bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h"
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
#include "../bugprone/UnsafeFunctionsCheck.h"
#include "../bugprone/UnusedReturnValueCheck.h"
@@ -278,6 +279,9 @@ class CERTModule : public ClangTidyModule {
"cert-oop58-cpp");
// C checkers
+ // ARR
+ CheckFactories.registerCheck<bugprone::SuspiciousPointerArithmeticsUsingSizeofCheck>(
+ "cert-arr39-c");
// CON
CheckFactories.registerCheck<bugprone::SpuriouslyWakeUpFunctionsCheck>(
"cert-con36-c");
>From f2d7d25549101d3250e65dc3a76dac766ccfc476 Mon Sep 17 00:00:00 2001
From: zporky <zporky at gmail.com>
Date: Fri, 3 Nov 2023 01:15:17 +0100
Subject: [PATCH 02/19] Working version of the checker.
---
...iousPointerArithmeticsUsingSizeofCheck.cpp | 21 +++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index abfa1bc7f037ea..de7c7e62e99282 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
+#include <iostream>
using namespace clang::ast_matchers;
@@ -24,13 +25,25 @@ SuspiciousPointerArithmeticsUsingSizeofCheck::SuspiciousPointerArithmeticsUsingS
void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- sizeOfExpr(expr())
- .bind("sizeof-expression"),
+ expr(anyOf(
+ binaryOperator(hasAnyOperatorName("+","-"),
+ hasEitherOperand(hasType(pointerType())),
+ hasEitherOperand(sizeOfExpr(expr())),
+ unless(allOf(hasLHS(hasType(pointerType())),
+ hasRHS(hasType(pointerType()))))
+ ).bind("ptr-sizeof-expression"),
+ binaryOperator(hasAnyOperatorName("+=","-="),
+ hasLHS(hasType(pointerType())),
+ hasRHS(sizeOfExpr(expr()))
+ ).bind("ptr-sizeof-expression")
+ )),
this);
}
-void SuspiciousPointerArithmeticsUsingSizeofCheck::check(
- const MatchFinder::MatchResult &Result) {
+void SuspiciousPointerArithmeticsUsingSizeofCheck::check(const MatchFinder::MatchResult &Result) {
+ static const char *diag_msg = "Suspicious pointer arithmetics using sizeof() operator";
+ auto Matched = Result.Nodes.getNodeAs<BinaryOperator>("ptr-sizeof-expression");
+ diag(Matched->getExprLoc(),diag_msg)<< Matched->getSourceRange();
}
} // namespace clang::tidy::bugprone
>From 330dc16f6b7db1a34596f03105c1560bf94fea07 Mon Sep 17 00:00:00 2001
From: zporky <zporky at gmail.com>
Date: Fri, 3 Nov 2023 21:23:26 +0100
Subject: [PATCH 03/19] Code simplification with elevating string constants.
---
.../SuspiciousPointerArithmeticsUsingSizeofCheck.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index de7c7e62e99282..90a8d308596cf6 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -12,10 +12,12 @@
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
-#include <iostream>
using namespace clang::ast_matchers;
+namespace {
+ static const char *bin_op_bind = "ptr-sizeof-expression";
+}
namespace clang::tidy::bugprone {
SuspiciousPointerArithmeticsUsingSizeofCheck::SuspiciousPointerArithmeticsUsingSizeofCheck(
@@ -31,18 +33,18 @@ void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(MatchFinder
hasEitherOperand(sizeOfExpr(expr())),
unless(allOf(hasLHS(hasType(pointerType())),
hasRHS(hasType(pointerType()))))
- ).bind("ptr-sizeof-expression"),
+ ).bind(bin_op_bind),
binaryOperator(hasAnyOperatorName("+=","-="),
hasLHS(hasType(pointerType())),
hasRHS(sizeOfExpr(expr()))
- ).bind("ptr-sizeof-expression")
+ ).bind(bin_op_bind)
)),
this);
}
void SuspiciousPointerArithmeticsUsingSizeofCheck::check(const MatchFinder::MatchResult &Result) {
static const char *diag_msg = "Suspicious pointer arithmetics using sizeof() operator";
- auto Matched = Result.Nodes.getNodeAs<BinaryOperator>("ptr-sizeof-expression");
+ auto Matched = Result.Nodes.getNodeAs<BinaryOperator>(bin_op_bind);
diag(Matched->getExprLoc(),diag_msg)<< Matched->getSourceRange();
}
>From 27a2ac5e7e6168c43dd9fec14994176b7ed18ea0 Mon Sep 17 00:00:00 2001
From: zporky <zporky at gmail.com>
Date: Thu, 9 Nov 2023 20:02:38 +0100
Subject: [PATCH 04/19] filtering out char* like matches
---
...iousPointerArithmeticsUsingSizeofCheck.cpp | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index 90a8d308596cf6..02275a2cdfe747 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -15,11 +15,13 @@
using namespace clang::ast_matchers;
-namespace {
- static const char *bin_op_bind = "ptr-sizeof-expression";
-}
namespace clang::tidy::bugprone {
+//static const char *bin_op_bind = "ptr-sizeof-expression";
+static constexpr llvm::StringLiteral BinOp{"bin-op"};
+static const auto IgnoredType = qualType(anyOf(asString("char"),asString("unsigned char"),asString("signed char"),asString("int8_t"),asString("uint8_t"),asString("std::byte"),asString("const char"),asString("const unsigned char"),asString("const signed char"),asString("const int8_t"),asString("const uint8_t"),asString("const std::byte")));
+static const auto InterestingPointer = pointerType(unless(pointee(IgnoredType)));
+
SuspiciousPointerArithmeticsUsingSizeofCheck::SuspiciousPointerArithmeticsUsingSizeofCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
@@ -28,7 +30,7 @@ SuspiciousPointerArithmeticsUsingSizeofCheck::SuspiciousPointerArithmeticsUsingS
void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
expr(anyOf(
- binaryOperator(hasAnyOperatorName("+","-"),
+/* binaryOperator(hasAnyOperatorName("+","-"),
hasEitherOperand(hasType(pointerType())),
hasEitherOperand(sizeOfExpr(expr())),
unless(allOf(hasLHS(hasType(pointerType())),
@@ -38,13 +40,20 @@ void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(MatchFinder
hasLHS(hasType(pointerType())),
hasRHS(sizeOfExpr(expr()))
).bind(bin_op_bind)
+*/
+ binaryOperator(hasAnyOperatorName("+=","-=","+","-" ),
+ hasLHS(hasType(InterestingPointer)),
+ hasRHS(sizeOfExpr(expr()))).bind(BinOp),
+ binaryOperator(hasAnyOperatorName("+","-" ),
+ hasRHS(hasType(InterestingPointer)),
+ hasLHS(sizeOfExpr(expr()))).bind(BinOp)
)),
this);
}
void SuspiciousPointerArithmeticsUsingSizeofCheck::check(const MatchFinder::MatchResult &Result) {
static const char *diag_msg = "Suspicious pointer arithmetics using sizeof() operator";
- auto Matched = Result.Nodes.getNodeAs<BinaryOperator>(bin_op_bind);
+ auto Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
diag(Matched->getExprLoc(),diag_msg)<< Matched->getSourceRange();
}
>From 3ed1e4fd39e9efd88e509637a345118a9a7b3300 Mon Sep 17 00:00:00 2001
From: zporky <zporky at gmail.com>
Date: Wed, 15 Nov 2023 23:03:45 +0100
Subject: [PATCH 05/19] Filtering out the uninteresting types in imperative
way.
---
...iousPointerArithmeticsUsingSizeofCheck.cpp | 29 +++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index 02275a2cdfe747..91f5ac55c508b6 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -19,6 +19,7 @@ namespace clang::tidy::bugprone {
//static const char *bin_op_bind = "ptr-sizeof-expression";
static constexpr llvm::StringLiteral BinOp{"bin-op"};
+static constexpr llvm::StringLiteral PointedType{"pointed-type"};
static const auto IgnoredType = qualType(anyOf(asString("char"),asString("unsigned char"),asString("signed char"),asString("int8_t"),asString("uint8_t"),asString("std::byte"),asString("const char"),asString("const unsigned char"),asString("const signed char"),asString("const int8_t"),asString("const uint8_t"),asString("const std::byte")));
static const auto InterestingPointer = pointerType(unless(pointee(IgnoredType)));
@@ -40,21 +41,43 @@ void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(MatchFinder
hasLHS(hasType(pointerType())),
hasRHS(sizeOfExpr(expr()))
).bind(bin_op_bind)
-*/
+
binaryOperator(hasAnyOperatorName("+=","-=","+","-" ),
hasLHS(hasType(InterestingPointer)),
hasRHS(sizeOfExpr(expr()))).bind(BinOp),
binaryOperator(hasAnyOperatorName("+","-" ),
hasRHS(hasType(InterestingPointer)),
hasLHS(sizeOfExpr(expr()))).bind(BinOp)
+*/
+ binaryOperator(hasAnyOperatorName("+=","-=","+","-" ),
+ hasLHS(hasType(pointerType(pointee(qualType().bind(PointedType))))),
+ hasRHS(sizeOfExpr(expr()))).bind(BinOp),
+ binaryOperator(hasAnyOperatorName("+","-" ),
+ hasRHS(hasType(pointerType(pointee(qualType().bind(PointedType))))),
+ hasLHS(sizeOfExpr(expr()))).bind(BinOp)
)),
this);
}
+static CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
+ if (!Ty || Ty->isIncompleteType() || Ty->isDependentType() ||
+ isa<DependentSizedArrayType>(Ty) || !Ty->isConstantSizeType())
+ return CharUnits::Zero();
+ return Ctx.getTypeSizeInChars(Ty);
+}
+
void SuspiciousPointerArithmeticsUsingSizeofCheck::check(const MatchFinder::MatchResult &Result) {
static const char *diag_msg = "Suspicious pointer arithmetics using sizeof() operator";
- auto Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
- diag(Matched->getExprLoc(),diag_msg)<< Matched->getSourceRange();
+ const ASTContext &Ctx = *Result.Context;
+ const auto Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
+ const auto SuspiciousQualTypePtr = Result.Nodes.getNodeAs<QualType>(PointedType);
+ const auto SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
+
+ auto sz = getSizeOfType(Ctx,SuspiciousTypePtr).getQuantity();
+ if ( sz > 1 )
+ {
+ diag(Matched->getExprLoc(),diag_msg)<< Matched->getSourceRange();
+ }
}
} // namespace clang::tidy::bugprone
>From 7e3b35dbf09d99fba55d42d9c4c5c571dd4703a6 Mon Sep 17 00:00:00 2001
From: zporky <zporky at gmail.com>
Date: Thu, 16 Nov 2023 20:35:03 +0100
Subject: [PATCH 06/19] Reporting the suspicious type and its size.
---
...SuspiciousPointerArithmeticsUsingSizeofCheck.cpp | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index 91f5ac55c508b6..a1710916f762ff 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -67,16 +67,17 @@ static CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
}
void SuspiciousPointerArithmeticsUsingSizeofCheck::check(const MatchFinder::MatchResult &Result) {
- static const char *diag_msg = "Suspicious pointer arithmetics using sizeof() operator";
const ASTContext &Ctx = *Result.Context;
- const auto Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
- const auto SuspiciousQualTypePtr = Result.Nodes.getNodeAs<QualType>(PointedType);
- const auto SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
+ const BinaryOperator* Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
+ const QualType* SuspiciousQualTypePtr = Result.Nodes.getNodeAs<QualType>(PointedType);
+ const Type* SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
- auto sz = getSizeOfType(Ctx,SuspiciousTypePtr).getQuantity();
+ std::size_t sz = getSizeOfType(Ctx,SuspiciousTypePtr).getQuantity();
if ( sz > 1 )
{
- diag(Matched->getExprLoc(),diag_msg)<< Matched->getSourceRange();
+ diag(Matched->getExprLoc(),"Suspicious pointer arithmetics using sizeof() operator: sizeof(%0) is %1") << SuspiciousQualTypePtr->getAsString(Ctx.getPrintingPolicy())
+ << sz
+ << Matched->getSourceRange();
}
}
>From fbbc8d2e75472ad8cdfdaef7f97083994f1ad3ef Mon Sep 17 00:00:00 2001
From: zporky <zporky at gmail.com>
Date: Fri, 5 Apr 2024 16:00:00 +0200
Subject: [PATCH 07/19] add initial test file
---
...picious-pointer-arithmetics-using-sizeof.c | 209 ++++++++++++++++++
1 file changed, 209 insertions(+)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
new file mode 100644
index 00000000000000..353cbcc9e683ae
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
@@ -0,0 +1,209 @@
+
+struct mystruct {
+ long a;
+ long b;
+ long c;
+};
+void noncompliant_f1(void);
+void compliant_f1(void);
+void noncompliant_f3(struct mystruct *msptr);
+void compliant_f3(struct mystruct *msptr);
+extern void sink(const char *);
+
+enum { bufsize = 1024 };
+
+void noncompliant_f1(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr;
+ while ( ptr < bptr + sizeof(buffer) ) { // noncompliant
+ *ptr++ = 0; // compliant
+ }
+}
+void noncompliant_f1a(void) {
+ typedef int my_int_t;
+ my_int_t buffer[bufsize];
+
+ my_int_t *bptr = &buffer[0];
+ my_int_t *ptr = bptr;
+ while ( ptr < bptr + sizeof(buffer) ) { // noncompliant
+ *ptr++ = 0; // compliant
+ }
+}
+void compliant_f1(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ *ptr++ = 0; // compliant
+ }
+}
+
+void noncompliant_f2(void) {
+ int buffer[bufsize];
+ int *ptr = buffer;
+
+ while ( ptr < buffer + sizeof(buffer) ) { // noncompliant
+ *ptr++ = 0; // compliant
+ }
+}
+
+void compliant_f2(void) {
+ int buffer[bufsize];
+ int *ptr = buffer;
+
+ while ( ptr < buffer + bufsize ) { // compliant
+ *ptr++ = 0; // compliant
+ }
+}
+
+void memset2(void*, int, unsigned int);
+
+void noncompliant_f3(struct mystruct *msptr) {
+ const unsigned int skip = sizeof(long); // why offsetof is declared?
+ struct mystruct *ptr = msptr;
+
+ memset2(ptr + skip, // noncompliant, impossible with tidy
+ 0, sizeof(struct mystruct) - skip);
+}
+
+void compliant_f3(struct mystruct *msptr) {
+ const unsigned int skip = sizeof(long);
+ char *ptr = (char*)msptr;
+
+ memset2(ptr + skip, // compliant
+ 0, sizeof(struct mystruct) - skip);
+}
+
+void noncompliant_f4(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ *ptr = 0;
+ ptr += sizeof(*ptr); // noncompliant
+ }
+}
+void noncompliant_f4w(void) { /* accidentally good */
+ char buffer[bufsize];
+
+ char *bptr = &buffer[0];
+ char *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ *ptr = 0;
+ ptr += sizeof(*ptr); // silenced
+ }
+}
+void compliant_f4w(void) {
+ char buffer[bufsize];
+
+ char *bptr = &buffer[0];
+ char *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ *ptr = 0;
+ ptr += 1; // compliant
+ }
+}
+
+void noncompliant_f5(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ *ptr = 0;
+ ptr = ptr + sizeof(*ptr); // noncompliant
+ }
+}
+void noncompliant_f5w(void) {
+ char buffer[bufsize];
+
+ char*bptr = &buffer[0];
+ char *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ *ptr = 0;
+ ptr = ptr + sizeof(*ptr); // silenced
+ }
+}
+void noncompliant_f5c(void) {
+ char buffer[bufsize];
+
+ char*bptr = &buffer[0];
+ const char *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ sink(ptr);
+ ptr = ptr + sizeof(*ptr); // silenced
+ }
+}
+void compliant_f5c(void) {
+ char buffer[bufsize];
+
+ char *bptr = &buffer[0];
+ const char *ptr = bptr;
+ while ( ptr < bptr + bufsize ) { // compliant
+ sink(ptr);
+ ptr = ptr + 1; // compliant
+ }
+}
+
+void noncompliant_f6(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr + bufsize; // compliant
+ while ( ptr >= bptr ) {
+ *ptr = 0;
+ ptr = ptr - sizeof(*ptr); // noncompliant
+ }
+}
+void noncompliant_f6w(void) {
+ char buffer[bufsize];
+
+ char *bptr = &buffer[0];
+ char *ptr = bptr + bufsize; // compliant
+ while ( ptr >= bptr ) {
+ *ptr = 0;
+ ptr = ptr - sizeof(*ptr); // silenced
+ }
+}
+void compliant_f6(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr + bufsize; // compliant
+ while ( ptr >= bptr ) {
+ *ptr = 0;
+ ptr = ptr - 1; // compliant
+ }
+}
+
+void compliant_f7(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr + bufsize; // compliant
+ int i = ptr - bptr; // compliant
+ while ( i >= 0 ) {
+ ptr[i] = 0;
+ i = i - 1; // compliant
+ }
+}
+
+void compliant_f8(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr + bufsize; // compliant
+ int i = sizeof(*ptr) - sizeof(*bptr); // compliant
+}
+void compliant_f9(void) {
+ int buffer[bufsize];
+
+ int *bptr = &buffer[0];
+ int *ptr = bptr + bufsize; // compliant
+ int i = sizeof(ptr) - sizeof(*bptr); // compliant
+}
+
>From 80c67e581ad2debed748d7142ed72a468936122a Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Mon, 26 Aug 2024 16:38:22 +0200
Subject: [PATCH 08/19] doc: Add documentation for the check
---
...iciousPointerArithmeticsUsingSizeofCheck.h | 15 ++++---
...cious-pointer-arithmetics-using-sizeof.rst | 44 +++++++++++++++++++
.../docs/clang-tidy/checks/cert/arr39-c.rst | 10 +++++
3 files changed, 62 insertions(+), 7 deletions(-)
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/cert/arr39-c.rst
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
index d39e15f0ccc3a0..1dbc51dd3df84f 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
@@ -6,25 +6,26 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSSIZEOFCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSSIZEOFCHECK_H
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSUSINGSIZEOFCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSUSINGSIZEOFCHECK_H
#include "../ClangTidyCheck.h"
namespace clang::tidy::bugprone {
-/// Find suspicious calls to string compare functions.
+/// Finds suspicious pointer arithmetic calculations where the pointer is
+/// offset by a sizeof() expression.
///
/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-sizeof.html
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.html
class SuspiciousPointerArithmeticsUsingSizeofCheck : public ClangTidyCheck {
public:
- SuspiciousPointerArithmeticsUsingSizeofCheck(StringRef Name, ClangTidyContext *Context);
-// void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ SuspiciousPointerArithmeticsUsingSizeofCheck(StringRef Name,
+ ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace clang::tidy::bugprone
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSSIZEOFCHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSPOINTERARITHMETICSUSINGSIZEOFCHECK_H
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
new file mode 100644
index 00000000000000..5188f947627ab0
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
@@ -0,0 +1,44 @@
+.. title:: clang-tidy - bugprone-suspicious-pointer-arithmetics-using-sizeof
+
+bugprone-suspicious-pointer-arithmetics-using-sizeof
+====================================================
+
+Finds suspicious pointer arithmetic calculations where the pointer is offset by a ``sizeof()`` expression.
+
+Pointer arithmetic expressions implicitly scale the offset added to or subtracted from the address by the size of the pointee type.
+Scaling the offset expression manually effectively results in a squared offset, which creates an invalid pointer that points beyond the end of the intended array.
+
+.. code-block:: c++
+
+ void printEveryEvenIndexElement(int *Array, size_t N) {
+ int *P = Array;
+ while (P <= Array + N * sizeof(int)) { // Suspicious pointer arithmetics using sizeof()!
+ printf("%d ", *P);
+
+ P += 2 * sizeof(int); // Suspicious pointer arithmetics using sizeof()!
+ }
+ }
+
+The above example should be in the following, correct form:
+
+.. code-block:: c++
+
+ void printEveryEvenIndexElement(int *Array, size_t N) {
+ int *P = Array;
+ while (P <= Array + N) {
+ printf("%d ", *P);
+
+ P += 2;
+ }
+ }
+
+`cert-arr39-c` redirects here as an alias of this check.
+
+This check corresponds to the CERT C Coding Standard rule
+`ARR39-C. Do not add or subtract a scaled integer to a pointer
+<http://wiki.sei.cmu.edu/confluence/display/c/ARR39-C.+Do+not+add+or+subtract+a+scaled+integer+to+a+pointer>`_.
+
+Limitations
+-----------
+
+While incorrect from a technically rigorous point of view, the check does not warn for pointer arithmetics where the pointee type is ``char`` (``sizeof(char) == 1``, by definition) on purpose.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/arr39-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/arr39-c.rst
new file mode 100644
index 00000000000000..91e02e39952be9
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/cert/arr39-c.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cert-arr39-c
+.. meta::
+ :http-equiv=refresh: 5;URL=../bugprone/suspicious-pointer-arithmetics-using-sizeof.html
+
+cert-arr39-c
+============
+
+The `cert-arr39-c` check is an alias, please see
+:doc:`bugprone-suspicious-pointer-arithmetics-using-sizeof <../bugprone/suspicious-pointer-arithmetics-using-sizeof>`
+for more information.
>From be6c05aa90caa29b7e6a7b9aff5fd3e3c7082c73 Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Mon, 26 Aug 2024 17:09:51 +0200
Subject: [PATCH 09/19] chore(doc): Added release notes entries
---
clang-tools-extra/docs/ReleaseNotes.rst | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 1b025e8f90f7ba..ba2ffb6f8970ff 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -98,9 +98,19 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
+- New :doc:`bugprone-suspicious-pointer-arithmetics-using-sizeof
+ <clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof>`
+ check that finds suspicious pointer arithmetic calculations where the pointer
+ is offset by a ``sizeof()`` expression.
+
New check aliases
^^^^^^^^^^^^^^^^^
+- New alias :doc:`cert-arr39-c <clang-tidy/checks/cert/arr39-c>` to
+ :doc:`bugprone-suspicious-pointer-arithmetics-using-sizeof
+ <clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof>`
+ was added.
+
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^
>From cc5de412e09f44df8489a817edc8f219d71f6557 Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Mon, 26 Aug 2024 17:11:50 +0200
Subject: [PATCH 10/19] style: Format out line break from `CERTModule`
---
clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
index 9e90f363367496..39ba55142da4bc 100644
--- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -283,8 +283,9 @@ class CERTModule : public ClangTidyModule {
// C checkers
// ARR
- CheckFactories.registerCheck<bugprone::SuspiciousPointerArithmeticsUsingSizeofCheck>(
- "cert-arr39-c");
+ CheckFactories
+ .registerCheck<bugprone::SuspiciousPointerArithmeticsUsingSizeofCheck>(
+ "cert-arr39-c");
// CON
CheckFactories.registerCheck<bugprone::SpuriouslyWakeUpFunctionsCheck>(
"cert-con36-c");
>From 590a7718fb39c918ca8182ab2782c2d235dc8c07 Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Mon, 26 Aug 2024 17:50:16 +0200
Subject: [PATCH 11/19] style: Apply some formatting fixes
---
.../SuspiciousPointerArithmeticsUsingSizeofCheck.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index a1710916f762ff..fc9c6eac38f91f 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -1,4 +1,4 @@
-//===--- SuspiciousPointerArithmeticsUsingSizeofCheck.cpp - clang-tidy --===//
+//===--- SuspiciousPointerArithmeticsUsingSizeofCheck.cpp - clang-tidy ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -68,9 +68,10 @@ static CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
void SuspiciousPointerArithmeticsUsingSizeofCheck::check(const MatchFinder::MatchResult &Result) {
const ASTContext &Ctx = *Result.Context;
- const BinaryOperator* Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
- const QualType* SuspiciousQualTypePtr = Result.Nodes.getNodeAs<QualType>(PointedType);
- const Type* SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
+ const auto *Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
+ const auto *SuspiciousQualTypePtr =
+ Result.Nodes.getNodeAs<QualType>(PointedType);
+ const auto *SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
std::size_t sz = getSizeOfType(Ctx,SuspiciousTypePtr).getQuantity();
if ( sz > 1 )
>From 294ed749fea17a0a5f654347afee8c69a36a2844 Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Mon, 26 Aug 2024 18:27:20 +0200
Subject: [PATCH 12/19] test: [wip] Start rewriting the test file (+ tear out
line ending whitespace)
---
...picious-pointer-arithmetics-using-sizeof.c | 156 ++++++++++--------
1 file changed, 83 insertions(+), 73 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
index 353cbcc9e683ae..7acd7c17681fb9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
@@ -1,3 +1,32 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-pointer-arithmetics-using-sizeof %t
+
+enum { BufferSize = 1024 };
+
+void bad1(void) {
+ int Buffer[BufferSize];
+
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + sizeof(Buffer)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this distance will be scaled again by the '+' operator [bugprone-suspicious-pointer-arithemetics-using-sizeof]
+ // CHECK-MESSAGES: :[[@LINE-2]]:18: note: 'sizeof(int)' == {{[0-9]+}}
+ *Q++ = 0;
+ }
+}
+
+void good1(void) {
+ int Buffer[BufferSize];
+
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + BufferSize) {
+ *Q++ = 0;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+
struct mystruct {
long a;
@@ -6,38 +35,20 @@ struct mystruct {
};
void noncompliant_f1(void);
void compliant_f1(void);
-void noncompliant_f3(struct mystruct *msptr);
+void noncompliant_f3(struct mystruct *msptr);
void compliant_f3(struct mystruct *msptr);
extern void sink(const char *);
enum { bufsize = 1024 };
-void noncompliant_f1(void) {
- int buffer[bufsize];
-
- int *bptr = &buffer[0];
- int *ptr = bptr;
- while ( ptr < bptr + sizeof(buffer) ) { // noncompliant
- *ptr++ = 0; // compliant
- }
-}
void noncompliant_f1a(void) {
- typedef int my_int_t;
- my_int_t buffer[bufsize];
+ typedef int my_int_t;
+ my_int_t buffer[bufsize];
- my_int_t *bptr = &buffer[0];
- my_int_t *ptr = bptr;
+ my_int_t *bptr = &buffer[0];
+ my_int_t *ptr = bptr;
while ( ptr < bptr + sizeof(buffer) ) { // noncompliant
- *ptr++ = 0; // compliant
- }
-}
-void compliant_f1(void) {
- int buffer[bufsize];
-
- int *bptr = &buffer[0];
- int *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- *ptr++ = 0; // compliant
+ *ptr++ = 0; // compliant
}
}
@@ -52,10 +63,10 @@ void noncompliant_f2(void) {
void compliant_f2(void) {
int buffer[bufsize];
- int *ptr = buffer;
+ int *ptr = buffer;
while ( ptr < buffer + bufsize ) { // compliant
- *ptr++ = 0; // compliant
+ *ptr++ = 0; // compliant
}
}
@@ -64,7 +75,7 @@ void memset2(void*, int, unsigned int);
void noncompliant_f3(struct mystruct *msptr) {
const unsigned int skip = sizeof(long); // why offsetof is declared?
struct mystruct *ptr = msptr;
-
+
memset2(ptr + skip, // noncompliant, impossible with tidy
0, sizeof(struct mystruct) - skip);
}
@@ -74,136 +85,135 @@ void compliant_f3(struct mystruct *msptr) {
char *ptr = (char*)msptr;
memset2(ptr + skip, // compliant
- 0, sizeof(struct mystruct) - skip);
+ 0, sizeof(struct mystruct) - skip);
}
void noncompliant_f4(void) {
- int buffer[bufsize];
+ int buffer[bufsize];
- int *bptr = &buffer[0];
- int *ptr = bptr;
+ int *bptr = &buffer[0];
+ int *ptr = bptr;
while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
+ *ptr = 0;
ptr += sizeof(*ptr); // noncompliant
}
}
void noncompliant_f4w(void) { /* accidentally good */
- char buffer[bufsize];
+ char buffer[bufsize];
- char *bptr = &buffer[0];
- char *ptr = bptr;
+ char *bptr = &buffer[0];
+ char *ptr = bptr;
while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
+ *ptr = 0;
ptr += sizeof(*ptr); // silenced
}
}
void compliant_f4w(void) {
- char buffer[bufsize];
+ char buffer[bufsize];
- char *bptr = &buffer[0];
- char *ptr = bptr;
+ char *bptr = &buffer[0];
+ char *ptr = bptr;
while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
+ *ptr = 0;
ptr += 1; // compliant
}
}
void noncompliant_f5(void) {
- int buffer[bufsize];
+ int buffer[bufsize];
- int *bptr = &buffer[0];
- int *ptr = bptr;
+ int *bptr = &buffer[0];
+ int *ptr = bptr;
while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
+ *ptr = 0;
ptr = ptr + sizeof(*ptr); // noncompliant
}
}
void noncompliant_f5w(void) {
- char buffer[bufsize];
+ char buffer[bufsize];
- char*bptr = &buffer[0];
- char *ptr = bptr;
+ char*bptr = &buffer[0];
+ char *ptr = bptr;
while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
+ *ptr = 0;
ptr = ptr + sizeof(*ptr); // silenced
}
}
void noncompliant_f5c(void) {
- char buffer[bufsize];
+ char buffer[bufsize];
- char*bptr = &buffer[0];
- const char *ptr = bptr;
+ char*bptr = &buffer[0];
+ const char *ptr = bptr;
while ( ptr < bptr + bufsize ) { // compliant
- sink(ptr);
+ sink(ptr);
ptr = ptr + sizeof(*ptr); // silenced
}
}
void compliant_f5c(void) {
- char buffer[bufsize];
+ char buffer[bufsize];
- char *bptr = &buffer[0];
- const char *ptr = bptr;
+ char *bptr = &buffer[0];
+ const char *ptr = bptr;
while ( ptr < bptr + bufsize ) { // compliant
- sink(ptr);
+ sink(ptr);
ptr = ptr + 1; // compliant
}
}
void noncompliant_f6(void) {
- int buffer[bufsize];
+ int buffer[bufsize];
- int *bptr = &buffer[0];
+ int *bptr = &buffer[0];
int *ptr = bptr + bufsize; // compliant
while ( ptr >= bptr ) {
- *ptr = 0;
+ *ptr = 0;
ptr = ptr - sizeof(*ptr); // noncompliant
}
}
void noncompliant_f6w(void) {
- char buffer[bufsize];
+ char buffer[bufsize];
- char *bptr = &buffer[0];
+ char *bptr = &buffer[0];
char *ptr = bptr + bufsize; // compliant
while ( ptr >= bptr ) {
- *ptr = 0;
+ *ptr = 0;
ptr = ptr - sizeof(*ptr); // silenced
}
}
void compliant_f6(void) {
- int buffer[bufsize];
+ int buffer[bufsize];
- int *bptr = &buffer[0];
+ int *bptr = &buffer[0];
int *ptr = bptr + bufsize; // compliant
while ( ptr >= bptr ) {
- *ptr = 0;
+ *ptr = 0;
ptr = ptr - 1; // compliant
}
}
void compliant_f7(void) {
- int buffer[bufsize];
+ int buffer[bufsize];
- int *bptr = &buffer[0];
+ int *bptr = &buffer[0];
int *ptr = bptr + bufsize; // compliant
int i = ptr - bptr; // compliant
while ( i >= 0 ) {
- ptr[i] = 0;
+ ptr[i] = 0;
i = i - 1; // compliant
}
}
void compliant_f8(void) {
- int buffer[bufsize];
+ int buffer[bufsize];
- int *bptr = &buffer[0];
+ int *bptr = &buffer[0];
int *ptr = bptr + bufsize; // compliant
int i = sizeof(*ptr) - sizeof(*bptr); // compliant
}
void compliant_f9(void) {
- int buffer[bufsize];
+ int buffer[bufsize];
- int *bptr = &buffer[0];
+ int *bptr = &buffer[0];
int *ptr = bptr + bufsize; // compliant
int i = sizeof(ptr) - sizeof(*bptr); // compliant
}
-
>From 7e44b452010bc978811aae57d362571146f68afa Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Tue, 27 Aug 2024 15:19:40 +0200
Subject: [PATCH 13/19] test: Implemented the tests with proper format and `//
CHECK` lines
---
...picious-pointer-arithmetics-using-sizeof.c | 352 +++++++++++-------
1 file changed, 223 insertions(+), 129 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
index 7acd7c17681fb9..8f2046ebdfa585 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
@@ -1,15 +1,33 @@
// RUN: %check_clang_tidy %s bugprone-suspicious-pointer-arithmetics-using-sizeof %t
+typedef __typeof__(sizeof(void*)) size_t;
+#define offsetof(type, member) __builtin_offsetof(type, member)
+extern void *memset(void *Dst, int Ch, size_t Count);
+extern void sink(const void *P);
+
enum { BufferSize = 1024 };
-void bad1(void) {
+void bad1a(void) {
int Buffer[BufferSize];
int *P = &Buffer[0];
int *Q = P;
while (Q < P + sizeof(Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this distance will be scaled again by the '+' operator [bugprone-suspicious-pointer-arithemetics-using-sizeof]
- // CHECK-MESSAGES: :[[@LINE-2]]:18: note: 'sizeof(int)' == {{[0-9]+}}
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(Buffer)' == {{[0-9]+}}
+ *Q++ = 0;
+ }
+}
+
+void bad1b(void) {
+ typedef int Integer;
+ Integer Buffer[BufferSize];
+
+ Integer *P = &Buffer[0];
+ Integer *Q = P;
+ while (Q < P + sizeof(Buffer)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this distance will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(Buffer)' == {{[0-9]+}}
*Q++ = 0;
}
}
@@ -24,196 +42,272 @@ void good1(void) {
}
}
+void bad2(void) {
+ int Buffer[BufferSize];
+ int *P = Buffer;
+
+ while (P < Buffer + sizeof(Buffer)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
+ *P++ = 0;
+ }
+}
-// ----------------------------------------------------------------------------
+void good2(void) {
+ int Buffer[BufferSize];
+ int *P = Buffer;
+ while (P < Buffer + BufferSize) {
+ *P++ = 0;
+ }
+}
-struct mystruct {
- long a;
- long b;
- long c;
+struct S {
+ long A, B, C;
};
-void noncompliant_f1(void);
-void compliant_f1(void);
-void noncompliant_f3(struct mystruct *msptr);
-void compliant_f3(struct mystruct *msptr);
-extern void sink(const char *);
-enum { bufsize = 1024 };
+void bad3a(struct S *S) {
+ const size_t Offset = offsetof(struct S, B);
+ struct S *P = S;
+
+ // This is not captureable by Tidy because the size/offset expression is
+ // not a direct child of the pointer arithmetics.
+ memset(P + Offset, 0, sizeof(struct S) - Offset);
+}
+
+void good3a(struct S *S) {
+ const size_t Offset = offsetof(struct S, B);
+ char *P = (char*)S;
-void noncompliant_f1a(void) {
- typedef int my_int_t;
- my_int_t buffer[bufsize];
+ // This is not captureable by Tidy because the size/offset expression is
+ // not a direct child of the pointer arithmetics.
+ memset(P + Offset, 0, sizeof(struct S) - Offset);
+}
+
+void bad3b(struct S *S) {
+ memset(S + offsetof(struct S, B), 0,
+ sizeof(struct S) - offsetof(struct S, B));
+ // NCHECK-MESSAGES: :[[@LINE-1]]:12: warning: pointer arithmetic using a number scaled by 'offsetof()'; this value will be scaled again by the '+' operator
+ // NCHECK-MESSAGES: :[[@LINE-2]]:12: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
+}
- my_int_t *bptr = &buffer[0];
- my_int_t *ptr = bptr;
- while ( ptr < bptr + sizeof(buffer) ) { // noncompliant
- *ptr++ = 0; // compliant
+void good3b(struct S *S) {
+ char *P = (char*)S;
+ memset(P + offsetof(struct S, B), 0,
+ sizeof(struct S) - offsetof(struct S, B));
+}
+
+void bad3c(void) {
+ struct S Buffer[BufferSize];
+
+ struct S *P = &Buffer[0];
+ struct S *Q = P;
+ while (Q < P + sizeof(Buffer)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(struct S)' == {{[0-9]+}}
+ sink(Q++);
}
}
-void noncompliant_f2(void) {
- int buffer[bufsize];
- int *ptr = buffer;
+void bad4(void) {
+ int Buffer[BufferSize];
- while ( ptr < buffer + sizeof(buffer) ) { // noncompliant
- *ptr++ = 0; // compliant
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q += sizeof(*Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
}
}
-void compliant_f2(void) {
- int buffer[bufsize];
- int *ptr = buffer;
+void silenced4(void) {
+ char Buffer[BufferSize];
- while ( ptr < buffer + bufsize ) { // compliant
- *ptr++ = 0; // compliant
+ char *P = &Buffer[0];
+ char *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q += sizeof(*Q);
}
}
-void memset2(void*, int, unsigned int);
+void good4(void) {
+ char Buffer[BufferSize];
-void noncompliant_f3(struct mystruct *msptr) {
- const unsigned int skip = sizeof(long); // why offsetof is declared?
- struct mystruct *ptr = msptr;
+ char *P = &Buffer[0];
+ char *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q += 1;
+ }
+}
- memset2(ptr + skip, // noncompliant, impossible with tidy
- 0, sizeof(struct mystruct) - skip);
+void good5aa(void) {
+ int Buffer[BufferSize];
+
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q += ( sizeof(Buffer)/ sizeof(Buffer[0]) );
+ }
}
-void compliant_f3(struct mystruct *msptr) {
- const unsigned int skip = sizeof(long);
- char *ptr = (char*)msptr;
+void good5ab(void) {
+ int Buffer[BufferSize];
- memset2(ptr + skip, // compliant
- 0, sizeof(struct mystruct) - skip);
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q = Q + ( sizeof(Buffer)/ sizeof(Buffer[0]) );
+ }
}
-void noncompliant_f4(void) {
- int buffer[bufsize];
+void good5ba(void) {
+ int Buffer[BufferSize];
- int *bptr = &buffer[0];
- int *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
- ptr += sizeof(*ptr); // noncompliant
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q -= ( sizeof(Buffer)/ sizeof(Buffer[0]) );
}
}
-void noncompliant_f4w(void) { /* accidentally good */
- char buffer[bufsize];
- char *bptr = &buffer[0];
- char *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
- ptr += sizeof(*ptr); // silenced
+void good5bb(void) {
+ int Buffer[BufferSize];
+
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q = Q - ( sizeof(Buffer)/ sizeof(Buffer[0]) );
}
}
-void compliant_f4w(void) {
- char buffer[bufsize];
- char *bptr = &buffer[0];
- char *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
- ptr += 1; // compliant
+void bad6(void) {
+ int Buffer[BufferSize];
+
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q = Q + sizeof(*Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
}
}
-void noncompliant_f5(void) {
- int buffer[bufsize];
+void silenced6(void) {
+ char Buffer[BufferSize];
- int *bptr = &buffer[0];
- int *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
- ptr = ptr + sizeof(*ptr); // noncompliant
+ char *P = &Buffer[0];
+ char *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q = Q + sizeof(*Q);
}
}
-void noncompliant_f5w(void) {
- char buffer[bufsize];
- char*bptr = &buffer[0];
- char *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- *ptr = 0;
- ptr = ptr + sizeof(*ptr); // silenced
+void good6(void) {
+ char Buffer[BufferSize];
+
+ char *P = &Buffer[0];
+ char *Q = P;
+ while (Q < P + BufferSize) {
+ *Q = 0;
+ Q = Q + 1;
}
}
-void noncompliant_f5c(void) {
- char buffer[bufsize];
- char*bptr = &buffer[0];
- const char *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- sink(ptr);
- ptr = ptr + sizeof(*ptr); // silenced
+void silenced7(void) {
+ char Buffer[BufferSize];
+
+ char *P = &Buffer[0];
+ const char *Q = P;
+ while (Q < P + BufferSize) {
+ sink(Q);
+ Q = Q + sizeof(*Q);
}
}
-void compliant_f5c(void) {
- char buffer[bufsize];
- char *bptr = &buffer[0];
- const char *ptr = bptr;
- while ( ptr < bptr + bufsize ) { // compliant
- sink(ptr);
- ptr = ptr + 1; // compliant
+void good7(void) {
+ char Buffer[BufferSize];
+
+ char *P = &Buffer[0];
+ const char *Q = P;
+ while (Q < P + BufferSize) {
+ sink(Q);
+ Q = Q + 1;
}
}
-void noncompliant_f6(void) {
- int buffer[bufsize];
+void bad8(void) {
+ int Buffer[BufferSize];
- int *bptr = &buffer[0];
- int *ptr = bptr + bufsize; // compliant
- while ( ptr >= bptr ) {
- *ptr = 0;
- ptr = ptr - sizeof(*ptr); // noncompliant
+ int *P = &Buffer[0];
+ int *Q = P;
+ while (Q >= P) {
+ *Q = 0;
+ Q = Q - sizeof(*Q);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '-' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:11: note: '-' scales with 'sizeof(int)' == {{[0-9]+}}
}
}
-void noncompliant_f6w(void) {
- char buffer[bufsize];
- char *bptr = &buffer[0];
- char *ptr = bptr + bufsize; // compliant
- while ( ptr >= bptr ) {
- *ptr = 0;
- ptr = ptr - sizeof(*ptr); // silenced
+void silenced8(void) {
+ char Buffer[BufferSize];
+
+ char *P = &Buffer[0];
+ char *Q = P;
+ while (Q >= P) {
+ *Q = 0;
+ Q = Q - sizeof(*Q);
}
}
-void compliant_f6(void) {
- int buffer[bufsize];
- int *bptr = &buffer[0];
- int *ptr = bptr + bufsize; // compliant
- while ( ptr >= bptr ) {
- *ptr = 0;
- ptr = ptr - 1; // compliant
+void good8(void) {
+ char Buffer[BufferSize];
+
+ char *P = &Buffer[0];
+ char *Q = P;
+ while (Q >= P) {
+ *Q = 0;
+ Q = Q - 1;
}
}
-void compliant_f7(void) {
- int buffer[bufsize];
+void good9(void) {
+ int Buffer[BufferSize];
- int *bptr = &buffer[0];
- int *ptr = bptr + bufsize; // compliant
- int i = ptr - bptr; // compliant
- while ( i >= 0 ) {
- ptr[i] = 0;
- i = i - 1; // compliant
+ int *P = &Buffer[0];
+ int *Q = P + BufferSize;
+ int N = Q - P;
+ while (N >= 0) {
+ Q[N] = 0;
+ N = N - 1;
}
}
-void compliant_f8(void) {
- int buffer[bufsize];
+void good10(void) {
+ int Buffer[BufferSize];
+
+ int *P = &Buffer[0];
+ int *Q = Buffer + BufferSize;
+ int I = sizeof(*P) - sizeof(*Q);
- int *bptr = &buffer[0];
- int *ptr = bptr + bufsize; // compliant
- int i = sizeof(*ptr) - sizeof(*bptr); // compliant
+ sink(&I);
}
-void compliant_f9(void) {
- int buffer[bufsize];
- int *bptr = &buffer[0];
- int *ptr = bptr + bufsize; // compliant
- int i = sizeof(ptr) - sizeof(*bptr); // compliant
+void good11(void) {
+ int Buffer[BufferSize];
+
+ int *P = &Buffer[0];
+ int *Q = Buffer + BufferSize;
+ int I = sizeof(Q) - sizeof(*P);
+
+ sink(&I);
}
>From 91288437f6f1543f351846a09e77c48175a2d74a Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Tue, 27 Aug 2024 15:24:30 +0200
Subject: [PATCH 14/19] style: [NFC] `clang-format` the check's main file
---
...iousPointerArithmeticsUsingSizeofCheck.cpp | 107 ++++++++++--------
1 file changed, 59 insertions(+), 48 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index fc9c6eac38f91f..86314d4d88b373 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -17,46 +17,56 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
-//static const char *bin_op_bind = "ptr-sizeof-expression";
+// static const char *bin_op_bind = "ptr-sizeof-expression";
static constexpr llvm::StringLiteral BinOp{"bin-op"};
static constexpr llvm::StringLiteral PointedType{"pointed-type"};
-static const auto IgnoredType = qualType(anyOf(asString("char"),asString("unsigned char"),asString("signed char"),asString("int8_t"),asString("uint8_t"),asString("std::byte"),asString("const char"),asString("const unsigned char"),asString("const signed char"),asString("const int8_t"),asString("const uint8_t"),asString("const std::byte")));
-static const auto InterestingPointer = pointerType(unless(pointee(IgnoredType)));
+static const auto IgnoredType = qualType(
+ anyOf(asString("char"), asString("unsigned char"), asString("signed char"),
+ asString("int8_t"), asString("uint8_t"), asString("std::byte"),
+ asString("const char"), asString("const unsigned char"),
+ asString("const signed char"), asString("const int8_t"),
+ asString("const uint8_t"), asString("const std::byte")));
+static const auto InterestingPointer =
+ pointerType(unless(pointee(IgnoredType)));
-SuspiciousPointerArithmeticsUsingSizeofCheck::SuspiciousPointerArithmeticsUsingSizeofCheck(
- StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {
-}
+SuspiciousPointerArithmeticsUsingSizeofCheck::
+ SuspiciousPointerArithmeticsUsingSizeofCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
-void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(
- expr(anyOf(
-/* binaryOperator(hasAnyOperatorName("+","-"),
- hasEitherOperand(hasType(pointerType())),
- hasEitherOperand(sizeOfExpr(expr())),
- unless(allOf(hasLHS(hasType(pointerType())),
- hasRHS(hasType(pointerType()))))
- ).bind(bin_op_bind),
- binaryOperator(hasAnyOperatorName("+=","-="),
- hasLHS(hasType(pointerType())),
- hasRHS(sizeOfExpr(expr()))
- ).bind(bin_op_bind)
+void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(
+ MatchFinder *Finder) {
+ Finder->addMatcher(
+ expr(anyOf(
+ /* binaryOperator(hasAnyOperatorName("+","-"),
+ hasEitherOperand(hasType(pointerType())),
+ hasEitherOperand(sizeOfExpr(expr())),
+ unless(allOf(hasLHS(hasType(pointerType())),
+ hasRHS(hasType(pointerType()))))
+ ).bind(bin_op_bind),
+ binaryOperator(hasAnyOperatorName("+=","-="),
+ hasLHS(hasType(pointerType())),
+ hasRHS(sizeOfExpr(expr()))
+ ).bind(bin_op_bind)
- binaryOperator(hasAnyOperatorName("+=","-=","+","-" ),
- hasLHS(hasType(InterestingPointer)),
- hasRHS(sizeOfExpr(expr()))).bind(BinOp),
- binaryOperator(hasAnyOperatorName("+","-" ),
- hasRHS(hasType(InterestingPointer)),
- hasLHS(sizeOfExpr(expr()))).bind(BinOp)
-*/
- binaryOperator(hasAnyOperatorName("+=","-=","+","-" ),
- hasLHS(hasType(pointerType(pointee(qualType().bind(PointedType))))),
- hasRHS(sizeOfExpr(expr()))).bind(BinOp),
- binaryOperator(hasAnyOperatorName("+","-" ),
- hasRHS(hasType(pointerType(pointee(qualType().bind(PointedType))))),
- hasLHS(sizeOfExpr(expr()))).bind(BinOp)
- )),
- this);
+ binaryOperator(hasAnyOperatorName("+=","-=","+","-"
+ ), hasLHS(hasType(InterestingPointer)),
+ hasRHS(sizeOfExpr(expr()))).bind(BinOp),
+ binaryOperator(hasAnyOperatorName("+","-" ),
+ hasRHS(hasType(InterestingPointer)),
+ hasLHS(sizeOfExpr(expr()))).bind(BinOp)
+ */
+ binaryOperator(hasAnyOperatorName("+=", "-=", "+", "-"),
+ hasLHS(hasType(pointerType(
+ pointee(qualType().bind(PointedType))))),
+ hasRHS(sizeOfExpr(expr())))
+ .bind(BinOp),
+ binaryOperator(hasAnyOperatorName("+", "-"),
+ hasRHS(hasType(pointerType(
+ pointee(qualType().bind(PointedType))))),
+ hasLHS(sizeOfExpr(expr())))
+ .bind(BinOp))),
+ this);
}
static CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
@@ -66,20 +76,21 @@ static CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
return Ctx.getTypeSizeInChars(Ty);
}
-void SuspiciousPointerArithmeticsUsingSizeofCheck::check(const MatchFinder::MatchResult &Result) {
- const ASTContext &Ctx = *Result.Context;
- const auto *Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
- const auto *SuspiciousQualTypePtr =
- Result.Nodes.getNodeAs<QualType>(PointedType);
- const auto *SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
+void SuspiciousPointerArithmeticsUsingSizeofCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const ASTContext &Ctx = *Result.Context;
+ const auto *Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
+ const auto *SuspiciousQualTypePtr =
+ Result.Nodes.getNodeAs<QualType>(PointedType);
+ const auto *SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
- std::size_t sz = getSizeOfType(Ctx,SuspiciousTypePtr).getQuantity();
- if ( sz > 1 )
- {
- diag(Matched->getExprLoc(),"Suspicious pointer arithmetics using sizeof() operator: sizeof(%0) is %1") << SuspiciousQualTypePtr->getAsString(Ctx.getPrintingPolicy())
- << sz
- << Matched->getSourceRange();
- }
+ std::size_t sz = getSizeOfType(Ctx, SuspiciousTypePtr).getQuantity();
+ if (sz > 1) {
+ diag(Matched->getExprLoc(), "Suspicious pointer arithmetics using sizeof() "
+ "operator: sizeof(%0) is %1")
+ << SuspiciousQualTypePtr->getAsString(Ctx.getPrintingPolicy()) << sz
+ << Matched->getSourceRange();
+ }
}
} // namespace clang::tidy::bugprone
>From 7ece46236db82af80dc871f3824dac74d90f0f80 Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Tue, 27 Aug 2024 15:42:18 +0200
Subject: [PATCH 15/19] wip: Refurbish the checker, improve code quality
---
...iousPointerArithmeticsUsingSizeofCheck.cpp | 96 ++++++++-----------
...ous-pointer-arithmetics-using-sizeof-c11.c | 22 +++++
...picious-pointer-arithmetics-using-sizeof.c | 12 +--
3 files changed, 70 insertions(+), 60 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index 86314d4d88b373..352d3e1ddb60c0 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -8,7 +8,6 @@
#include "SuspiciousPointerArithmeticsUsingSizeofCheck.h"
#include "../utils/Matchers.h"
-#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
@@ -17,17 +16,30 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
-// static const char *bin_op_bind = "ptr-sizeof-expression";
-static constexpr llvm::StringLiteral BinOp{"bin-op"};
-static constexpr llvm::StringLiteral PointedType{"pointed-type"};
-static const auto IgnoredType = qualType(
+namespace {
+
+constexpr llvm::StringLiteral BinOp{"bin-op"};
+constexpr llvm::StringLiteral PointedType{"pointed-type"};
+constexpr llvm::StringLiteral ScaleExpr{"scale-expr"};
+
+const auto IgnoredTypes = qualType(
anyOf(asString("char"), asString("unsigned char"), asString("signed char"),
asString("int8_t"), asString("uint8_t"), asString("std::byte"),
asString("const char"), asString("const unsigned char"),
asString("const signed char"), asString("const int8_t"),
asString("const uint8_t"), asString("const std::byte")));
-static const auto InterestingPointer =
- pointerType(unless(pointee(IgnoredType)));
+const auto InterestingPointer = pointerType(unless(pointee(IgnoredTypes)));
+
+const auto ScaledIntegerTraitExprs = /*stmt(anyOf(*/ sizeOfExpr(expr()) /*))*/;
+
+CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
+ if (!Ty || Ty->isIncompleteType() || Ty->isDependentType() ||
+ isa<DependentSizedArrayType>(Ty) || !Ty->isConstantSizeType())
+ return CharUnits::Zero();
+ return Ctx.getTypeSizeInChars(Ty);
+}
+
+} // namespace
SuspiciousPointerArithmeticsUsingSizeofCheck::
SuspiciousPointerArithmeticsUsingSizeofCheck(StringRef Name,
@@ -37,60 +49,36 @@ SuspiciousPointerArithmeticsUsingSizeofCheck::
void SuspiciousPointerArithmeticsUsingSizeofCheck::registerMatchers(
MatchFinder *Finder) {
Finder->addMatcher(
- expr(anyOf(
- /* binaryOperator(hasAnyOperatorName("+","-"),
- hasEitherOperand(hasType(pointerType())),
- hasEitherOperand(sizeOfExpr(expr())),
- unless(allOf(hasLHS(hasType(pointerType())),
- hasRHS(hasType(pointerType()))))
- ).bind(bin_op_bind),
- binaryOperator(hasAnyOperatorName("+=","-="),
- hasLHS(hasType(pointerType())),
- hasRHS(sizeOfExpr(expr()))
- ).bind(bin_op_bind)
-
- binaryOperator(hasAnyOperatorName("+=","-=","+","-"
- ), hasLHS(hasType(InterestingPointer)),
- hasRHS(sizeOfExpr(expr()))).bind(BinOp),
- binaryOperator(hasAnyOperatorName("+","-" ),
- hasRHS(hasType(InterestingPointer)),
- hasLHS(sizeOfExpr(expr()))).bind(BinOp)
- */
- binaryOperator(hasAnyOperatorName("+=", "-=", "+", "-"),
- hasLHS(hasType(pointerType(
- pointee(qualType().bind(PointedType))))),
- hasRHS(sizeOfExpr(expr())))
- .bind(BinOp),
- binaryOperator(hasAnyOperatorName("+", "-"),
- hasRHS(hasType(pointerType(
- pointee(qualType().bind(PointedType))))),
- hasLHS(sizeOfExpr(expr())))
- .bind(BinOp))),
+ expr(anyOf(binaryOperator(hasAnyOperatorName("+", "+=", "-", "-="),
+ hasLHS(hasType(pointerType(
+ pointee(qualType().bind(PointedType))))),
+ hasRHS(ScaledIntegerTraitExprs.bind(ScaleExpr)))
+ .bind(BinOp),
+ binaryOperator(hasAnyOperatorName("+", "-"),
+ hasRHS(hasType(pointerType(
+ pointee(qualType().bind(PointedType))))),
+ hasLHS(ScaledIntegerTraitExprs.bind(ScaleExpr)))
+ .bind(BinOp))),
this);
}
-static CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
- if (!Ty || Ty->isIncompleteType() || Ty->isDependentType() ||
- isa<DependentSizedArrayType>(Ty) || !Ty->isConstantSizeType())
- return CharUnits::Zero();
- return Ctx.getTypeSizeInChars(Ty);
-}
-
void SuspiciousPointerArithmeticsUsingSizeofCheck::check(
const MatchFinder::MatchResult &Result) {
const ASTContext &Ctx = *Result.Context;
- const auto *Matched = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
- const auto *SuspiciousQualTypePtr =
- Result.Nodes.getNodeAs<QualType>(PointedType);
- const auto *SuspiciousTypePtr = SuspiciousQualTypePtr->getTypePtr();
+ const auto *BO = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
+ const auto *QT = Result.Nodes.getNodeAs<QualType>(PointedType);
+ assert(BO && QT && "Broken matchers encountered.");
+
+ const auto Size = getSizeOfType(Ctx, QT->getTypePtr()).getQuantity();
+ if (Size == 1)
+ return;
- std::size_t sz = getSizeOfType(Ctx, SuspiciousTypePtr).getQuantity();
- if (sz > 1) {
- diag(Matched->getExprLoc(), "Suspicious pointer arithmetics using sizeof() "
- "operator: sizeof(%0) is %1")
- << SuspiciousQualTypePtr->getAsString(Ctx.getPrintingPolicy()) << sz
- << Matched->getSourceRange();
- }
+ diag(BO->getExprLoc(),
+ "pointer arithmetic using a number scaled by '%0'; this value will be "
+ "scaled again by the '%1' operator")
+ << "sizeof" << BO->getOpcodeStr();
+ diag(BO->getExprLoc(), "'%0' scales with '%1(%2)' == %3", DiagnosticIDs::Note)
+ << BO->getOpcodeStr() << "sizeof" << "?" << Size;
}
} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c
new file mode 100644
index 00000000000000..f00cb11b217caf
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy --std=c11-or-later %s bugprone-suspicious-pointer-arithmetics-using-sizeof %t
+
+#define alignof(type_name) _Alignof(type_name)
+extern void sink(const void *P);
+
+enum { BufferSize = 1024 };
+
+struct S {
+ long A, B, C;
+};
+
+void bad4d(void) {
+ struct S Buffer[BufferSize];
+
+ struct S *P = &Buffer[0];
+ struct S *Q = P;
+ while (Q < P + alignof(Buffer)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'alignof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(struct S)' == {{[0-9]+}}
+ sink(Q++);
+ }
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
index 8f2046ebdfa585..840eaf38b18f19 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
@@ -117,8 +117,8 @@ void bad4(void) {
while (Q < P + BufferSize) {
*Q = 0;
Q += sizeof(*Q);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
- // CHECK-MESSAGES: :[[@LINE-2]]:7: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+=' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: note: '+=' scales with 'sizeof(int)' == {{[0-9]+}}
}
}
@@ -151,7 +151,7 @@ void good5aa(void) {
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
- Q += ( sizeof(Buffer)/ sizeof(Buffer[0]) );
+ Q += ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}
@@ -162,7 +162,7 @@ void good5ab(void) {
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
- Q = Q + ( sizeof(Buffer)/ sizeof(Buffer[0]) );
+ Q = Q + ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}
@@ -173,7 +173,7 @@ void good5ba(void) {
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
- Q -= ( sizeof(Buffer)/ sizeof(Buffer[0]) );
+ Q -= ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}
@@ -184,7 +184,7 @@ void good5bb(void) {
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
- Q = Q - ( sizeof(Buffer)/ sizeof(Buffer[0]) );
+ Q = Q - ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}
>From cfe5be1229282e28f5de814557302f3b37e57267 Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Tue, 27 Aug 2024 16:19:04 +0200
Subject: [PATCH 16/19] feat: Match `alignof()` and `offsetof()` as well
---
...iousPointerArithmeticsUsingSizeofCheck.cpp | 40 +++++++++++++++----
...iciousPointerArithmeticsUsingSizeofCheck.h | 2 +-
clang-tools-extra/docs/ReleaseNotes.rst | 2 +-
...cious-pointer-arithmetics-using-sizeof.rst | 4 +-
...ous-pointer-arithmetics-using-sizeof-c11.c | 4 +-
...picious-pointer-arithmetics-using-sizeof.c | 24 +++++------
6 files changed, 50 insertions(+), 26 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
index 352d3e1ddb60c0..7a77bec319559b 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.cpp
@@ -30,7 +30,11 @@ const auto IgnoredTypes = qualType(
asString("const uint8_t"), asString("const std::byte")));
const auto InterestingPointer = pointerType(unless(pointee(IgnoredTypes)));
-const auto ScaledIntegerTraitExprs = /*stmt(anyOf(*/ sizeOfExpr(expr()) /*))*/;
+AST_MATCHER(Expr, offsetOfExpr) { return isa<OffsetOfExpr>(Node); }
+
+const auto ScaledIntegerTraitExprs =
+ expr(anyOf(unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf)),
+ unaryExprOrTypeTraitExpr(ofKind(UETT_AlignOf)), offsetOfExpr()));
CharUnits getSizeOfType(const ASTContext &Ctx, const Type *Ty) {
if (!Ty || Ty->isIncompleteType() || Ty->isDependentType() ||
@@ -67,18 +71,38 @@ void SuspiciousPointerArithmeticsUsingSizeofCheck::check(
const ASTContext &Ctx = *Result.Context;
const auto *BO = Result.Nodes.getNodeAs<BinaryOperator>(BinOp);
const auto *QT = Result.Nodes.getNodeAs<QualType>(PointedType);
- assert(BO && QT && "Broken matchers encountered.");
+ const auto *ScaleE = Result.Nodes.getNodeAs<Expr>(ScaleExpr);
+ assert(BO && QT && ScaleE && "Broken matchers encountered.");
const auto Size = getSizeOfType(Ctx, QT->getTypePtr()).getQuantity();
if (Size == 1)
return;
- diag(BO->getExprLoc(),
- "pointer arithmetic using a number scaled by '%0'; this value will be "
- "scaled again by the '%1' operator")
- << "sizeof" << BO->getOpcodeStr();
- diag(BO->getExprLoc(), "'%0' scales with '%1(%2)' == %3", DiagnosticIDs::Note)
- << BO->getOpcodeStr() << "sizeof" << "?" << Size;
+ const int KindSelect = [ScaleE]() {
+ if (const auto *UTTE = dyn_cast<UnaryExprOrTypeTraitExpr>(ScaleE))
+ switch (UTTE->getKind()) {
+ case UETT_SizeOf:
+ return 0;
+ case UETT_AlignOf:
+ return 1;
+ default:
+ return -1;
+ }
+
+ if (isa<OffsetOfExpr>(ScaleE))
+ return 2;
+
+ return -1;
+ }();
+ assert(KindSelect != -1 && "Unhandled scale-expr kind!");
+
+ diag(BO->getExprLoc(), "pointer arithmetic using a number scaled by "
+ "'%select{sizeof|alignof|offsetof}0'; this value will "
+ "be scaled again by the '%1' operator")
+ << KindSelect << BO->getOpcodeStr() << ScaleE->getSourceRange();
+ diag(BO->getExprLoc(), "'%0' scales with 'sizeof(%1)' == %2",
+ DiagnosticIDs::Note)
+ << BO->getOpcodeStr() << QT->getAsString(Ctx.getPrintingPolicy()) << Size;
}
} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
index 1dbc51dd3df84f..bfafd1a1296423 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
@@ -14,7 +14,7 @@
namespace clang::tidy::bugprone {
/// Finds suspicious pointer arithmetic calculations where the pointer is
-/// offset by a sizeof() expression.
+/// offset by an alignof(), offsetof(), or sizeof() expression.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.html
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index ba2ffb6f8970ff..c87781b1f2caa3 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -101,7 +101,7 @@ New checks
- New :doc:`bugprone-suspicious-pointer-arithmetics-using-sizeof
<clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof>`
check that finds suspicious pointer arithmetic calculations where the pointer
- is offset by a ``sizeof()`` expression.
+ is offset by an ``alignof()``, ``offsetof()``, or ``sizeof()`` expression.
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
index 5188f947627ab0..a00eaf6ac84353 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
@@ -3,10 +3,10 @@
bugprone-suspicious-pointer-arithmetics-using-sizeof
====================================================
-Finds suspicious pointer arithmetic calculations where the pointer is offset by a ``sizeof()`` expression.
+Finds suspicious pointer arithmetic calculations where the pointer is offset by an ``alignof()``, ``offsetof()``, or ``sizeof()`` expression.
Pointer arithmetic expressions implicitly scale the offset added to or subtracted from the address by the size of the pointee type.
-Scaling the offset expression manually effectively results in a squared offset, which creates an invalid pointer that points beyond the end of the intended array.
+Using an offset expression that is already scaled by the size of the underlying type effectively results in a squared offset, which is likely an invalid pointer that points beyond the end of the intended array.
.. code-block:: c++
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c
index f00cb11b217caf..33bf69bdea1185 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof-c11.c
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy --std=c11-or-later %s bugprone-suspicious-pointer-arithmetics-using-sizeof %t
+// RUN: %check_clang_tidy -std=c11-or-later %s bugprone-suspicious-pointer-arithmetics-using-sizeof %t
#define alignof(type_name) _Alignof(type_name)
extern void sink(const void *P);
@@ -15,7 +15,7 @@ void bad4d(void) {
struct S *P = &Buffer[0];
struct S *Q = P;
while (Q < P + alignof(Buffer)) {
- // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'alignof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'alignof'; this value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(struct S)' == {{[0-9]+}}
sink(Q++);
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
index 840eaf38b18f19..5a834b85565d49 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-pointer-arithmetics-using-sizeof.c
@@ -13,8 +13,8 @@ void bad1a(void) {
int *P = &Buffer[0];
int *Q = P;
while (Q < P + sizeof(Buffer)) {
- // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this distance will be scaled again by the '+' operator [bugprone-suspicious-pointer-arithemetics-using-sizeof]
- // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(Buffer)' == {{[0-9]+}}
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof'; this value will be scaled again by the '+' operator [bugprone-suspicious-pointer-arithmetics-using-sizeof]
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
*Q++ = 0;
}
}
@@ -26,8 +26,8 @@ void bad1b(void) {
Integer *P = &Buffer[0];
Integer *Q = P;
while (Q < P + sizeof(Buffer)) {
- // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this distance will be scaled again by the '+' operator
- // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(Buffer)' == {{[0-9]+}}
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(Integer)' == {{[0-9]+}}
*Q++ = 0;
}
}
@@ -47,8 +47,8 @@ void bad2(void) {
int *P = Buffer;
while (P < Buffer + sizeof(Buffer)) {
- // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
- // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: pointer arithmetic using a number scaled by 'sizeof'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-2]]:21: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
*P++ = 0;
}
}
@@ -87,8 +87,8 @@ void good3a(struct S *S) {
void bad3b(struct S *S) {
memset(S + offsetof(struct S, B), 0,
sizeof(struct S) - offsetof(struct S, B));
- // NCHECK-MESSAGES: :[[@LINE-1]]:12: warning: pointer arithmetic using a number scaled by 'offsetof()'; this value will be scaled again by the '+' operator
- // NCHECK-MESSAGES: :[[@LINE-2]]:12: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
+ // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: pointer arithmetic using a number scaled by 'offsetof'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-3]]:12: note: '+' scales with 'sizeof(struct S)' == {{[0-9]+}}
}
void good3b(struct S *S) {
@@ -103,7 +103,7 @@ void bad3c(void) {
struct S *P = &Buffer[0];
struct S *Q = P;
while (Q < P + sizeof(Buffer)) {
- // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: pointer arithmetic using a number scaled by 'sizeof'; this value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' scales with 'sizeof(struct S)' == {{[0-9]+}}
sink(Q++);
}
@@ -117,7 +117,7 @@ void bad4(void) {
while (Q < P + BufferSize) {
*Q = 0;
Q += sizeof(*Q);
- // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+=' operator
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: pointer arithmetic using a number scaled by 'sizeof'; this value will be scaled again by the '+=' operator
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: '+=' scales with 'sizeof(int)' == {{[0-9]+}}
}
}
@@ -196,7 +196,7 @@ void bad6(void) {
while (Q < P + BufferSize) {
*Q = 0;
Q = Q + sizeof(*Q);
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '+' operator
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: pointer arithmetic using a number scaled by 'sizeof'; this value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:11: note: '+' scales with 'sizeof(int)' == {{[0-9]+}}
}
}
@@ -253,7 +253,7 @@ void bad8(void) {
while (Q >= P) {
*Q = 0;
Q = Q - sizeof(*Q);
- // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: pointer arithmetic using a number scaled by 'sizeof()'; this value will be scaled again by the '-' operator
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: pointer arithmetic using a number scaled by 'sizeof'; this value will be scaled again by the '-' operator
// CHECK-MESSAGES: :[[@LINE-2]]:11: note: '-' scales with 'sizeof(int)' == {{[0-9]+}}
}
}
>From 0bad4f8f85ac3aac073f04c1bb66e8c305317c5e Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Tue, 27 Aug 2024 16:26:10 +0200
Subject: [PATCH 17/19] style: `clang-format`
---
clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
index 39ba55142da4bc..ce5c2a119f4528 100644
--- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -284,8 +284,8 @@ class CERTModule : public ClangTidyModule {
// C checkers
// ARR
CheckFactories
- .registerCheck<bugprone::SuspiciousPointerArithmeticsUsingSizeofCheck>(
- "cert-arr39-c");
+ .registerCheck<bugprone::SuspiciousPointerArithmeticsUsingSizeofCheck>(
+ "cert-arr39-c");
// CON
CheckFactories.registerCheck<bugprone::SpuriouslyWakeUpFunctionsCheck>(
"cert-con36-c");
>From 69449326575b2725de54990744c80cc6ca49dfef Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Tue, 27 Aug 2024 16:26:51 +0200
Subject: [PATCH 18/19] style: `clang-format`
---
.../bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
index bfafd1a1296423..fdce44a7a24394 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousPointerArithmeticsUsingSizeofCheck.h
@@ -1,4 +1,4 @@
-//===--- SuspiciousPointerArithmeticsUsingSizeofCheck.h - clang-tidy -*- C++ -*-===//
+//===--- SuspiciousPointerArithmeticsUsingSizeofCheck.h -------*- C++ -*---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 067b855c10a6cfd1409c276f9fa1acc58a0ada01 Mon Sep 17 00:00:00 2001
From: Whisperity <whisperity at gmail.com>
Date: Tue, 27 Aug 2024 16:29:47 +0200
Subject: [PATCH 19/19] style: Reformat RST changes
---
clang-tools-extra/docs/ReleaseNotes.rst | 6 ++++--
...icious-pointer-arithmetics-using-sizeof.rst | 18 ++++++++++++------
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index d25339f4a03165..039a7af8d0f03a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -100,8 +100,10 @@ New checks
- New :doc:`bugprone-suspicious-pointer-arithmetics-using-sizeof
<clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof>`
- check that finds suspicious pointer arithmetic calculations where the pointer
- is offset by an ``alignof()``, ``offsetof()``, or ``sizeof()`` expression.
+ check.
+
+ Finds suspicious pointer arithmetic calculations where the pointer is offset
+ by an ``alignof()``, ``offsetof()``, or ``sizeof()`` expression.
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
index a00eaf6ac84353..805e489d06e881 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-pointer-arithmetics-using-sizeof.rst
@@ -3,12 +3,16 @@
bugprone-suspicious-pointer-arithmetics-using-sizeof
====================================================
-Finds suspicious pointer arithmetic calculations where the pointer is offset by an ``alignof()``, ``offsetof()``, or ``sizeof()`` expression.
+Finds suspicious pointer arithmetic calculations where the pointer is offset by
+an ``alignof()``, ``offsetof()``, or ``sizeof()`` expression.
-Pointer arithmetic expressions implicitly scale the offset added to or subtracted from the address by the size of the pointee type.
-Using an offset expression that is already scaled by the size of the underlying type effectively results in a squared offset, which is likely an invalid pointer that points beyond the end of the intended array.
+Pointer arithmetic expressions implicitly scale the offset added to or
+subtracted from the address by the size of the pointee type.
+Using an offset expression that is already scaled by the size of the underlying
+type effectively results in a squared offset, which is likely an invalid
+pointer that points beyond the end of the intended array.
-.. code-block:: c++
+.. code-block:: c
void printEveryEvenIndexElement(int *Array, size_t N) {
int *P = Array;
@@ -21,7 +25,7 @@ Using an offset expression that is already scaled by the size of the underlying
The above example should be in the following, correct form:
-.. code-block:: c++
+.. code-block:: c
void printEveryEvenIndexElement(int *Array, size_t N) {
int *P = Array;
@@ -41,4 +45,6 @@ This check corresponds to the CERT C Coding Standard rule
Limitations
-----------
-While incorrect from a technically rigorous point of view, the check does not warn for pointer arithmetics where the pointee type is ``char`` (``sizeof(char) == 1``, by definition) on purpose.
+While incorrect from a technically rigorous point of view, the check does not
+warn for pointer arithmetics where the pointee type is ``char``
+(``sizeof(char) == 1``, by definition) on purpose.
More information about the cfe-commits
mailing list