[clang-tools-extra] fccd0da - [clang-tidy] New check: bugprone-misplaced-pointer-arithmetic-in-alloc

Adam Balogh via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 21 05:36:07 PST 2020


Author: Adam Balogh
Date: 2020-01-21T14:38:15+01:00
New Revision: fccd0da5ee6f4e337395f287edcf824a009e1b7e

URL: https://github.com/llvm/llvm-project/commit/fccd0da5ee6f4e337395f287edcf824a009e1b7e
DIFF: https://github.com/llvm/llvm-project/commit/fccd0da5ee6f4e337395f287edcf824a009e1b7e.diff

LOG: [clang-tidy] New check: bugprone-misplaced-pointer-arithmetic-in-alloc

Finds cases where an integer expression is added to the result
of a memory allocation function instead of its argument.

Differential Revision: https://reviews.llvm.org/D71001

Added: 
    clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
    clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h
    clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc.rst
    clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.c
    clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp

Modified: 
    clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
    clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 831f5f4e3b62..86936c678562 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "MacroParenthesesCheck.h"
 #include "MacroRepeatedSideEffectsCheck.h"
 #include "MisplacedOperatorInStrlenInAllocCheck.h"
+#include "MisplacedPointerArithmeticInAllocCheck.h"
 #include "MisplacedWideningCastCheck.h"
 #include "MoveForwardingReferenceCheck.h"
 #include "MultipleStatementMacroCheck.h"
@@ -107,6 +108,8 @@ class BugproneModule : public ClangTidyModule {
         "bugprone-macro-repeated-side-effects");
     CheckFactories.registerCheck<MisplacedOperatorInStrlenInAllocCheck>(
         "bugprone-misplaced-operator-in-strlen-in-alloc");
+    CheckFactories.registerCheck<MisplacedPointerArithmeticInAllocCheck>(
+        "bugprone-misplaced-pointer-arithmetic-in-alloc");
     CheckFactories.registerCheck<MisplacedWideningCastCheck>(
         "bugprone-misplaced-widening-cast");
     CheckFactories.registerCheck<MoveForwardingReferenceCheck>(

diff  --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index efb97a5318bb..c9078ed390d1 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -22,6 +22,7 @@ add_clang_library(clangTidyBugproneModule
   MacroParenthesesCheck.cpp
   MacroRepeatedSideEffectsCheck.cpp
   MisplacedOperatorInStrlenInAllocCheck.cpp
+  MisplacedPointerArithmeticInAllocCheck.cpp
   MisplacedWideningCastCheck.cpp
   MoveForwardingReferenceCheck.cpp
   MultipleStatementMacroCheck.cpp

diff  --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
new file mode 100644
index 000000000000..c6dc78622851
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.cpp
@@ -0,0 +1,105 @@
+//===--- MisplacedPointerArithmeticInAllocCheck.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 "MisplacedPointerArithmeticInAllocCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+void MisplacedPointerArithmeticInAllocCheck::registerMatchers(
+    MatchFinder *Finder) {
+  const auto AllocFunc = functionDecl(
+      anyOf(hasName("::malloc"), hasName("std::malloc"), hasName("::alloca"),
+            hasName("::calloc"), hasName("std::calloc"), hasName("::realloc"),
+            hasName("std::realloc")));
+
+  const auto AllocFuncPtr =
+      varDecl(hasType(isConstQualified()),
+              hasInitializer(ignoringParenImpCasts(
+                  declRefExpr(hasDeclaration(AllocFunc)))));
+
+  const auto AdditiveOperator =
+      binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")));
+
+  const auto IntExpr = expr(hasType(isInteger()));
+
+  const auto AllocCall = callExpr(callee(decl(anyOf(AllocFunc, AllocFuncPtr))));
+
+  Finder->addMatcher(
+      binaryOperator(
+          AdditiveOperator,
+          hasLHS(anyOf(AllocCall, castExpr(hasSourceExpression(AllocCall)))),
+          hasRHS(IntExpr))
+          .bind("PtrArith"),
+      this);
+
+  const auto New = cxxNewExpr(unless(isArray()));
+
+  Finder->addMatcher(binaryOperator(AdditiveOperator,
+                                    hasLHS(anyOf(New, castExpr(New))),
+                                    hasRHS(IntExpr))
+                         .bind("PtrArith"),
+                     this);
+
+  const auto ArrayNew = cxxNewExpr(isArray());
+
+  Finder->addMatcher(binaryOperator(AdditiveOperator,
+                                    hasLHS(anyOf(ArrayNew, castExpr(ArrayNew))),
+                                    hasRHS(IntExpr))
+                         .bind("PtrArith"),
+                     this);
+}
+
+void MisplacedPointerArithmeticInAllocCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *PtrArith = Result.Nodes.getNodeAs<BinaryOperator>("PtrArith");
+  const Expr *AllocExpr = PtrArith->getLHS()->IgnoreParenCasts();
+  std::string CallName;
+
+  if (const auto *Call = dyn_cast<CallExpr>(AllocExpr)) {
+    const NamedDecl *Func = Call->getDirectCallee();
+    if (!Func) {
+      Func = cast<NamedDecl>(Call->getCalleeDecl());
+    }
+    CallName = Func->getName().str();
+  } else {
+    const auto *New = cast<CXXNewExpr>(AllocExpr);
+    if (New->isArray()) {
+      CallName = "operator new[]";
+    } else {
+      const auto *CtrE = New->getConstructExpr();
+      if (!CtrE->getArg(CtrE->getNumArgs() - 1)
+               ->getType()
+               ->isIntegralOrEnumerationType())
+        return;
+      CallName = "operator new";
+    }
+  }
+
+  const SourceRange OldRParen = SourceRange(PtrArith->getLHS()->getEndLoc());
+  const StringRef RParen =
+      Lexer::getSourceText(CharSourceRange::getTokenRange(OldRParen),
+                           *Result.SourceManager, getLangOpts());
+  const SourceLocation NewRParen = Lexer::getLocForEndOfToken(
+      PtrArith->getEndLoc(), 0, *Result.SourceManager, getLangOpts());
+
+  diag(PtrArith->getBeginLoc(),
+       "arithmetic operation is applied to the result of %0() instead of its "
+       "size-like argument")
+      << CallName << FixItHint::CreateRemoval(OldRParen)
+      << FixItHint::CreateInsertion(NewRParen, RParen);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang

diff  --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h
new file mode 100644
index 000000000000..e1b767bc9083
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h
@@ -0,0 +1,36 @@
+//===--- MisplacedPointerArithmeticInAllocCheck.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_MISPLACED_OPERATOR_IN_ALLOC_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_ALLOC_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds cases where an integer is added to or subracted from the result of a
+/// memory allocation function instead of its argument.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-misplaced-operator-in-alloc.html
+class MisplacedPointerArithmeticInAllocCheck : public ClangTidyCheck {
+public:
+  MisplacedPointerArithmeticInAllocCheck(StringRef Name,
+                                         ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_ALLOC_H

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 1e0f76b17c5c..196ab3fe8c11 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -70,6 +70,13 @@ Improvements to clang-tidy
 New checks
 ^^^^^^^^^^
 
+- New :doc:`bugprone-misplaced-pointer-arithmetic-in-alloc
+  <clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc>` check.
+
+  Finds cases where an integer expression is added to or subtracted from the
+  result of a memory allocation function (``malloc()``, ``calloc()``,
+  ``realloc()``, ``alloca()``) instead of its argument.
+
 - New :doc:`bugprone-reserved-identifier
   <clang-tidy/checks/bugprone-reserved-identifier>` check.
 

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc.rst
new file mode 100644
index 000000000000..4a3606da0250
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-pointer-arithmetic-in-alloc.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - bugprone-misplaced-pointer-arithmetic-in-alloc
+
+bugprone-misplaced-pointer-artithmetic-in-alloc
+===============================================
+
+Finds cases where an integer expression is added to or subtracted from the
+result of a memory allocation function (``malloc()``, ``calloc()``,
+``realloc()``, ``alloca()``) instead of its argument. The check detects error
+cases even if one of these functions is called by a constant function pointer.
+
+Example code:
+
+.. code-block:: c
+
+  void bad_malloc(int n) {
+    char *p = (char*) malloc(n) + 10;
+  }
+
+
+The suggested fix is to add the integer expression to the argument of
+``malloc`` and not to its result. In the example above the fix would be
+
+.. code-block:: c
+
+  char *p = (char*) malloc(n + 10);

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index c958837ae4ba..a6796e118d23 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@ Clang-Tidy Checks
    `bugprone-macro-parentheses <bugprone-macro-parentheses.html>`_, "Yes"
    `bugprone-macro-repeated-side-effects <bugprone-macro-repeated-side-effects.html>`_,
    `bugprone-misplaced-operator-in-strlen-in-alloc <bugprone-misplaced-operator-in-strlen-in-alloc.html>`_, "Yes"
+   `bugprone-misplaced-pointer-arithmetic-in-alloc <bugprone-misplaced-pointer-arithmetic-in-alloc.html>`_, "Yes"
    `bugprone-misplaced-widening-cast <bugprone-misplaced-widening-cast.html>`_,
    `bugprone-move-forwarding-reference <bugprone-move-forwarding-reference.html>`_, "Yes"
    `bugprone-multiple-statement-macro <bugprone-multiple-statement-macro.html>`_,

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.c
new file mode 100644
index 000000000000..c5878da70637
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.c
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-pointer-arithmetic-in-alloc %t
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void *alloca(size_t);
+void *calloc(size_t, size_t);
+void *realloc(void *, size_t);
+
+void bad_malloc(int n) {
+  char *p = (char *)malloc(n) + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: arithmetic operation is applied to the result of malloc() instead of its size-like argument
+  // CHECK-FIXES: char *p = (char *)malloc(n + 10);
+
+  p = (char *)malloc(n) - 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of malloc() instead of its size-like argument
+  // CHECK-FIXES: p = (char *)malloc(n - 10);
+
+  p = (char *)malloc(n) + n;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of malloc() instead of its size-like argument
+  // CHECK-FIXES: p = (char *)malloc(n + n);
+
+  p = (char *)malloc(n) - (n + 10);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of malloc() instead of its size-like argument
+  // CHECK-FIXES: p = (char *)malloc(n - (n + 10));
+
+  p = (char *)malloc(n) - n + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of malloc() instead of its size-like argument
+  // CHECK-FIXES: p = (char *)malloc(n - n) + 10;
+  // FIXME: should be p = (char *)malloc(n - n + 10);
+}
+
+void bad_alloca(int n) {
+  char *p = (char *)alloca(n) + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: arithmetic operation is applied to the result of alloca() instead of its size-like argument
+  // CHECK-FIXES: char *p = (char *)alloca(n + 10);
+}
+
+void bad_realloc(char *s, int n) {
+  char *p = (char *)realloc(s, n) + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: arithmetic operation is applied to the result of realloc() instead of its size-like argument
+  // CHECK-FIXES: char *p = (char *)realloc(s, n + 10);
+}
+
+void bad_calloc(int n, int m) {
+  char *p = (char *)calloc(m, n) + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: arithmetic operation is applied to the result of calloc() instead of its size-like argument
+  // CHECK-FIXES: char *p = (char *)calloc(m, n + 10);
+}
+
+void (*(*const alloc_ptr)(size_t)) = malloc;
+
+void bad_indirect_alloc(int n) {
+  char *p = (char *)alloc_ptr(n) + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: arithmetic operation is applied to the result of alloc_ptr() instead of its size-like argument
+  // CHECK-FIXES: char *p = (char *)alloc_ptr(n + 10);
+}

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp
new file mode 100644
index 000000000000..42250da2610d
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-misplaced-pointer-arithmetic-in-alloc.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy %s bugprone-misplaced-pointer-arithmetic-in-alloc %t
+
+class C {
+  int num;
+public:
+  explicit C(int n) : num(n) {}
+};
+
+void bad_new(int n, int m) {
+  C *p = new C(n) + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: arithmetic operation is applied to the result of operator new() instead of its size-like argument
+  // CHECK-FIXES: C *p = new C(n + 10);
+
+  p = new C(n) - 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new() instead of its size-like argument
+  // CHECK-FIXES: p = new C(n - 10);
+
+  p = new C(n) + m;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new() instead of its size-like argument
+  // CHECK-FIXES: p = new C(n + m);
+
+  p = new C(n) - (m + 10);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new() instead of its size-like argument
+  // CHECK-FIXES: p = new C(n - (m + 10));
+
+  p = new C(n) - m + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new() instead of its size-like argument
+  // CHECK-FIXES: p = new C(n - m) + 10;
+  // FIXME: Should be p = new C(n - m + 10);
+}
+
+void bad_new_array(int n, int m) {
+  char *p = new char[n] + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: arithmetic operation is applied to the result of operator new[]() instead of its size-like argument
+  // CHECK-FIXES: char *p = new char[n + 10];
+
+  p = new char[n] - 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new[]() instead of its size-like argument
+  // CHECK-FIXES: p = new char[n - 10];
+
+  p = new char[n] + m;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new[]() instead of its size-like argument
+  // CHECK-FIXES: p = new char[n + m];
+
+  p = new char[n] - (m + 10);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new[]() instead of its size-like argument
+  // CHECK-FIXES: p = new char[n - (m + 10)];
+
+  p = new char[n] - m + 10;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: arithmetic operation is applied to the result of operator new[]() instead of its size-like argument
+  // CHECK-FIXES: p = new char[n - m] + 10;
+  // FIXME: should be p = new char[n - m + 10];
+}


        


More information about the cfe-commits mailing list