forked from OSchip/llvm-project
[clang-tidy] Add bugprone-bad-signal-to-kill-thread check and its alias cert-pos44-c
This commit is contained in:
parent
8cec7e0208
commit
8d288a0668
|
@ -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
|
|
@ -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
|
|
@ -12,6 +12,7 @@
|
||||||
#include "../cppcoreguidelines/NarrowingConversionsCheck.h"
|
#include "../cppcoreguidelines/NarrowingConversionsCheck.h"
|
||||||
#include "ArgumentCommentCheck.h"
|
#include "ArgumentCommentCheck.h"
|
||||||
#include "AssertSideEffectCheck.h"
|
#include "AssertSideEffectCheck.h"
|
||||||
|
#include "BadSignalToKillThreadCheck.h"
|
||||||
#include "BoolPointerImplicitConversionCheck.h"
|
#include "BoolPointerImplicitConversionCheck.h"
|
||||||
#include "BranchCloneCheck.h"
|
#include "BranchCloneCheck.h"
|
||||||
#include "CopyConstructorInitCheck.h"
|
#include "CopyConstructorInitCheck.h"
|
||||||
|
@ -68,6 +69,8 @@ public:
|
||||||
"bugprone-argument-comment");
|
"bugprone-argument-comment");
|
||||||
CheckFactories.registerCheck<AssertSideEffectCheck>(
|
CheckFactories.registerCheck<AssertSideEffectCheck>(
|
||||||
"bugprone-assert-side-effect");
|
"bugprone-assert-side-effect");
|
||||||
|
CheckFactories.registerCheck<BadSignalToKillThreadCheck>(
|
||||||
|
"bugprone-bad-signal-to-kill-thread");
|
||||||
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
|
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
|
||||||
"bugprone-bool-pointer-implicit-conversion");
|
"bugprone-bool-pointer-implicit-conversion");
|
||||||
CheckFactories.registerCheck<BranchCloneCheck>(
|
CheckFactories.registerCheck<BranchCloneCheck>(
|
||||||
|
|
|
@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
|
||||||
add_clang_library(clangTidyBugproneModule
|
add_clang_library(clangTidyBugproneModule
|
||||||
ArgumentCommentCheck.cpp
|
ArgumentCommentCheck.cpp
|
||||||
AssertSideEffectCheck.cpp
|
AssertSideEffectCheck.cpp
|
||||||
|
BadSignalToKillThreadCheck.cpp
|
||||||
BoolPointerImplicitConversionCheck.cpp
|
BoolPointerImplicitConversionCheck.cpp
|
||||||
BranchCloneCheck.cpp
|
BranchCloneCheck.cpp
|
||||||
BugproneTidyModule.cpp
|
BugproneTidyModule.cpp
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "../ClangTidyModule.h"
|
#include "../ClangTidyModule.h"
|
||||||
#include "../ClangTidyModuleRegistry.h"
|
#include "../ClangTidyModuleRegistry.h"
|
||||||
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
|
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
|
||||||
|
#include "../bugprone/BadSignalToKillThreadCheck.h"
|
||||||
#include "../google/UnnamedNamespaceInHeaderCheck.h"
|
#include "../google/UnnamedNamespaceInHeaderCheck.h"
|
||||||
#include "../misc/NewDeleteOverloadsCheck.h"
|
#include "../misc/NewDeleteOverloadsCheck.h"
|
||||||
#include "../misc/NonCopyableObjects.h"
|
#include "../misc/NonCopyableObjects.h"
|
||||||
|
@ -82,6 +83,9 @@ public:
|
||||||
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
|
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
|
||||||
CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
|
CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
|
||||||
"cert-msc32-c");
|
"cert-msc32-c");
|
||||||
|
// POS
|
||||||
|
CheckFactories.registerCheck<bugprone::BadSignalToKillThreadCheck>(
|
||||||
|
"cert-pos44-c");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangTidyOptions getModuleOptions() override {
|
ClangTidyOptions getModuleOptions() override {
|
||||||
|
|
|
@ -67,6 +67,12 @@ The improvements are...
|
||||||
Improvements to clang-tidy
|
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
|
- New :doc:`bugprone-dynamic-static-initializers
|
||||||
<clang-tidy/checks/bugprone-dynamic-static-initializers>` check.
|
<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
|
Without the null terminator it can result in undefined behaviour when the
|
||||||
string is read.
|
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
|
- New :doc:`cppcoreguidelines-init-variables
|
||||||
<clang-tidy/checks/cppcoreguidelines-init-variables>` check.
|
<clang-tidy/checks/cppcoreguidelines-init-variables>` check.
|
||||||
|
|
||||||
|
|
|
@ -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>`_.
|
|
@ -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.
|
|
@ -39,6 +39,7 @@ Clang-Tidy Checks
|
||||||
boost-use-to-string
|
boost-use-to-string
|
||||||
bugprone-argument-comment
|
bugprone-argument-comment
|
||||||
bugprone-assert-side-effect
|
bugprone-assert-side-effect
|
||||||
|
bugprone-bad-signal-to-kill-thread
|
||||||
bugprone-bool-pointer-implicit-conversion
|
bugprone-bool-pointer-implicit-conversion
|
||||||
bugprone-branch-clone
|
bugprone-branch-clone
|
||||||
bugprone-copy-constructor-init
|
bugprone-copy-constructor-init
|
||||||
|
@ -105,6 +106,7 @@ Clang-Tidy Checks
|
||||||
cert-msc51-cpp
|
cert-msc51-cpp
|
||||||
cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-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-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.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.DivideZero (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.DivideZero>
|
||||||
clang-analyzer-core.DynamicTypePropagation
|
clang-analyzer-core.DynamicTypePropagation
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue