mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 19:45:40 -04:00
[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
This commit is contained in:
parent
5181c67feb
commit
fccd0da5ee
@ -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 @@ public:
|
||||
"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>(
|
||||
|
@ -22,6 +22,7 @@ add_clang_library(clangTidyBugproneModule
|
||||
MacroParenthesesCheck.cpp
|
||||
MacroRepeatedSideEffectsCheck.cpp
|
||||
MisplacedOperatorInStrlenInAllocCheck.cpp
|
||||
MisplacedPointerArithmeticInAllocCheck.cpp
|
||||
MisplacedWideningCastCheck.cpp
|
||||
MoveForwardingReferenceCheck.cpp
|
||||
MultipleStatementMacroCheck.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
|
@ -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
|
@ -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.
|
||||
|
||||
|
@ -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);
|
@ -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>`_,
|
||||
|
@ -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);
|
||||
}
|
@ -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];
|
||||
}
|
Loading…
Reference in New Issue
Block a user