[clang-tidy] Add bugprone-bad-signal-to-kill-thread check and its alias cert-pos44-c

This commit is contained in:
Abel Kocsis 2019-11-11 17:47:14 +01:00
parent 8cec7e0208
commit 8d288a0668
10 changed files with 191 additions and 0 deletions

View File

@ -0,0 +1,70 @@
//===--- BadSignalToKillThreadCheck.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 "BadSignalToKillThreadCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
void BadSignalToKillThreadCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
callExpr(allOf(callee(functionDecl(hasName("::pthread_kill"))),
argumentCountIs(2)),
hasArgument(1, integerLiteral().bind("integer-literal")))
.bind("thread-kill"),
this);
}
static Preprocessor *PP;
void BadSignalToKillThreadCheck::check(const MatchFinder::MatchResult &Result) {
const auto IsSigterm = [](const auto &KeyValue) -> bool {
return KeyValue.first->getName() == "SIGTERM";
};
const auto TryExpandAsInteger =
[](Preprocessor::macro_iterator It) -> Optional<unsigned> {
if (It == PP->macro_end())
return llvm::None;
const MacroInfo *MI = PP->getMacroInfo(It->first);
const Token &T = MI->tokens().back();
StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength());
llvm::APInt IntValue;
constexpr unsigned AutoSenseRadix = 0;
if (ValueStr.getAsInteger(AutoSenseRadix, IntValue))
return llvm::None;
return IntValue.getZExtValue();
};
const auto SigtermMacro = llvm::find_if(PP->macros(), IsSigterm);
if (!SigtermValue && !(SigtermValue = TryExpandAsInteger(SigtermMacro)))
return;
const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("thread-kill");
const auto *MatchedIntLiteral =
Result.Nodes.getNodeAs<IntegerLiteral>("integer-literal");
if (MatchedIntLiteral->getValue() == *SigtermValue) {
diag(MatchedExpr->getBeginLoc(),
"thread should not be terminated by raising the 'SIGTERM' signal");
}
}
void BadSignalToKillThreadCheck::registerPPCallbacks(
const SourceManager &SM, Preprocessor *pp, Preprocessor *ModuleExpanderPP) {
PP = pp;
}
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,37 @@
//===--- BadSignalToKillThreadCheck.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_BADSIGNALTOKILLTHREADCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BADSIGNALTOKILLTHREADCHECK_H
#include "../ClangTidyCheck.h"
namespace clang {
namespace tidy {
namespace bugprone {
/// Finds ``pthread_kill`` function calls when thread is terminated by
/// ``SIGTERM`` signal.
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-bad-signal-to-kill-thread.html
class BadSignalToKillThreadCheck : public ClangTidyCheck {
public:
BadSignalToKillThreadCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
Preprocessor *ModuleExpanderPP) override;
Optional<unsigned> SigtermValue;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BADSIGNALTOKILLTHREADCHECK_H

View File

@ -12,6 +12,7 @@
#include "../cppcoreguidelines/NarrowingConversionsCheck.h"
#include "ArgumentCommentCheck.h"
#include "AssertSideEffectCheck.h"
#include "BadSignalToKillThreadCheck.h"
#include "BoolPointerImplicitConversionCheck.h"
#include "BranchCloneCheck.h"
#include "CopyConstructorInitCheck.h"
@ -68,6 +69,8 @@ public:
"bugprone-argument-comment");
CheckFactories.registerCheck<AssertSideEffectCheck>(
"bugprone-assert-side-effect");
CheckFactories.registerCheck<BadSignalToKillThreadCheck>(
"bugprone-bad-signal-to-kill-thread");
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
"bugprone-bool-pointer-implicit-conversion");
CheckFactories.registerCheck<BranchCloneCheck>(

View File

@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyBugproneModule
ArgumentCommentCheck.cpp
AssertSideEffectCheck.cpp
BadSignalToKillThreadCheck.cpp
BoolPointerImplicitConversionCheck.cpp
BranchCloneCheck.cpp
BugproneTidyModule.cpp

View File

@ -10,6 +10,7 @@
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
#include "../bugprone/BadSignalToKillThreadCheck.h"
#include "../google/UnnamedNamespaceInHeaderCheck.h"
#include "../misc/NewDeleteOverloadsCheck.h"
#include "../misc/NonCopyableObjects.h"
@ -82,6 +83,9 @@ public:
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
"cert-msc32-c");
// POS
CheckFactories.registerCheck<bugprone::BadSignalToKillThreadCheck>(
"cert-pos44-c");
}
ClangTidyOptions getModuleOptions() override {

View File

@ -67,6 +67,12 @@ The improvements are...
Improvements to clang-tidy
--------------------------
- New :doc:`bugprone-bad-signal-to-kill-thread
<clang-tidy/checks/bugprone-bad-signal-to-kill-thread>` check.
Finds ``pthread_kill`` function calls when a thread is terminated by
raising ``SIGTERM`` signal.
- New :doc:`bugprone-dynamic-static-initializers
<clang-tidy/checks/bugprone-dynamic-static-initializers>` check.
@ -88,6 +94,11 @@ Improvements to clang-tidy
Without the null terminator it can result in undefined behaviour when the
string is read.
- New alias :doc:`cert-pos44-cpp
<clang-tidy/checks/cert-pos44-cpp>` to
:doc:`bugprone-bad-signal-to-kill-thread
<clang-tidy/checks/bugprone-bad-signal-to-kill-thread>` was added.
- New :doc:`cppcoreguidelines-init-variables
<clang-tidy/checks/cppcoreguidelines-init-variables>` check.

View File

@ -0,0 +1,16 @@
.. title:: clang-tidy - bugprone-bad-signal-to-kill-thread
bugprone-bad-signal-to-kill-thread
==================================
Finds ``pthread_kill`` function calls when a thread is terminated by
raising ``SIGTERM`` signal and the signal kills the entire process, not
just the individual thread. Use any signal except ``SIGTERM``.
.. code-block: c++
pthread_kill(thread, SIGTERM);
This check corresponds to the CERT C Coding Standard rule
`POS44-C. Do not use signals to terminate threads
<https://wiki.sei.cmu.edu/confluence/display/c/POS44-C.+Do+not+use+signals+to+terminate+threads>`_.

View File

@ -0,0 +1,9 @@
.. title:: clang-tidy - cert-pos44-c
.. meta::
:http-equiv=refresh: 5;URL=bugprone-bad-signal-to-kill-thread.html
cert-pos44-c
============
The cert-pos44-c check is an alias, please see
`bugprone-bad-signal-to-kill-thread <bugprone-bad-signal-to-kill-thread.html>`_ for more information.

View File

@ -39,6 +39,7 @@ Clang-Tidy Checks
boost-use-to-string
bugprone-argument-comment
bugprone-assert-side-effect
bugprone-bad-signal-to-kill-thread
bugprone-bool-pointer-implicit-conversion
bugprone-branch-clone
bugprone-copy-constructor-init
@ -105,6 +106,7 @@ Clang-Tidy Checks
cert-msc51-cpp
cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-cpp>
cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) <cert-oop54-cpp>
cert-pos44-c (redirects to bugprone-bad-signal-to-kill-thread) <cert-pos44-c>
clang-analyzer-core.CallAndMessage (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.CallAndMessage>
clang-analyzer-core.DivideZero (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.DivideZero>
clang-analyzer-core.DynamicTypePropagation

View File

@ -0,0 +1,38 @@
// RUN: %check_clang_tidy %s bugprone-bad-signal-to-kill-thread %t
#define SIGTERM 15
#define SIGINT 2
using pthread_t = int;
using pthread_attr_t = int;
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
int pthread_kill(pthread_t thread, int sig);
int pthread_cancel(pthread_t thread);
void *test_func_return_a_pointer(void *foo);
int main() {
int result;
pthread_t thread;
if ((result = pthread_create(&thread, nullptr, test_func_return_a_pointer, 0)) != 0) {
}
if ((result = pthread_kill(thread, SIGTERM)) != 0) {
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: thread should not be terminated by raising the 'SIGTERM' signal [bugprone-bad-signal-to-kill-thread]
}
//compliant solution
if ((result = pthread_cancel(thread)) != 0) {
}
if ((result = pthread_kill(thread, SIGINT)) != 0) {
}
if ((result = pthread_kill(thread, 0xF)) != 0) {
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: thread should not be terminated by raising the 'SIGTERM' signal [bugprone-bad-signal-to-kill-thread]
}
return 0;
}