Skip to content

Commit 4edf0cb

Browse files
author
Abel Kocsis
committed
[clang-tidy] Add bugprone-bad-signal-to-kill-thread checker and alias cert-pos44-c
1 parent fdf3d17 commit 4edf0cb

11 files changed

+1324
-0
lines changed

bad-signal-to-kill-thread.patch

Lines changed: 1133 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===--- BadSignalToKillThreadCheck.cpp - clang-tidy ---------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "BadSignalToKillThreadCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
13+
using namespace clang::ast_matchers;
14+
15+
namespace clang {
16+
namespace tidy {
17+
namespace bugprone {
18+
19+
void BadSignalToKillThreadCheck::registerMatchers(MatchFinder *Finder) {
20+
Finder->addMatcher(
21+
callExpr(allOf(callee(functionDecl(hasName("::pthread_kill"))),
22+
argumentCountIs(2)),
23+
hasArgument(1, integerLiteral().bind("integer-literal")))
24+
.bind("thread-kill"),
25+
this);
26+
}
27+
28+
static Preprocessor *PP;
29+
30+
void BadSignalToKillThreadCheck::check(const MatchFinder::MatchResult &Result) {
31+
const auto IsSigterm = [](const auto &KeyValue) -> bool {
32+
return KeyValue.first->getName() == "SIGTERM";
33+
};
34+
const auto TryExpandAsInteger =
35+
[](Preprocessor::macro_iterator It) -> Optional<unsigned> {
36+
if (It == PP->macro_end())
37+
return llvm::None;
38+
const MacroInfo *MI = PP->getMacroInfo(It->first);
39+
const Token &T = MI->tokens().back();
40+
StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength());
41+
42+
llvm::APInt IntValue;
43+
constexpr unsigned AutoSenseRadix = 0;
44+
if (ValueStr.getAsInteger(AutoSenseRadix, IntValue))
45+
return llvm::None;
46+
return IntValue.getZExtValue();
47+
};
48+
49+
const auto SigtermMacro = llvm::find_if(PP->macros(), IsSigterm);
50+
51+
if (!SigtermValue && !(SigtermValue = TryExpandAsInteger(SigtermMacro)))
52+
return;
53+
54+
const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("thread-kill");
55+
const auto *MatchedIntLiteral =
56+
Result.Nodes.getNodeAs<IntegerLiteral>("integer-literal");
57+
if (MatchedIntLiteral->getValue() == *SigtermValue) {
58+
diag(MatchedExpr->getBeginLoc(),
59+
"thread should not be terminated by raising the 'SIGTERM' signal");
60+
}
61+
}
62+
63+
void BadSignalToKillThreadCheck::registerPPCallbacks(
64+
const SourceManager &SM, Preprocessor *pp, Preprocessor *ModuleExpanderPP) {
65+
PP = pp;
66+
}
67+
68+
} // namespace bugprone
69+
} // namespace tidy
70+
} // namespace clang
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===--- BadSignalToKillThreadCheck.h - clang-tidy --------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BADSIGNALTOKILLTHREADCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BADSIGNALTOKILLTHREADCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang {
15+
namespace tidy {
16+
namespace bugprone {
17+
18+
/// Finds ``pthread_kill`` function calls when thread is terminated by
19+
/// ``SIGTERM`` signal.
20+
/// For the user-facing documentation see:
21+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-bad-signal-to-kill-thread.html
22+
class BadSignalToKillThreadCheck : public ClangTidyCheck {
23+
public:
24+
BadSignalToKillThreadCheck(StringRef Name, ClangTidyContext *Context)
25+
: ClangTidyCheck(Name, Context) {}
26+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
27+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
28+
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
29+
Preprocessor *ModuleExpanderPP) override;
30+
Optional<unsigned> SigtermValue;
31+
};
32+
33+
} // namespace bugprone
34+
} // namespace tidy
35+
} // namespace clang
36+
37+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_BADSIGNALTOKILLTHREADCHECK_H

clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "../cppcoreguidelines/NarrowingConversionsCheck.h"
1313
#include "ArgumentCommentCheck.h"
1414
#include "AssertSideEffectCheck.h"
15+
#include "BadSignalToKillThreadCheck.h"
1516
#include "BoolPointerImplicitConversionCheck.h"
1617
#include "BranchCloneCheck.h"
1718
#include "CopyConstructorInitCheck.h"
@@ -68,6 +69,8 @@ class BugproneModule : public ClangTidyModule {
6869
"bugprone-argument-comment");
6970
CheckFactories.registerCheck<AssertSideEffectCheck>(
7071
"bugprone-assert-side-effect");
72+
CheckFactories.registerCheck<BadSignalToKillThreadCheck>(
73+
"bugprone-bad-signal-to-kill-thread");
7174
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
7275
"bugprone-bool-pointer-implicit-conversion");
7376
CheckFactories.registerCheck<BranchCloneCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
33
add_clang_library(clangTidyBugproneModule
44
ArgumentCommentCheck.cpp
55
AssertSideEffectCheck.cpp
6+
BadSignalToKillThreadCheck.cpp
67
BoolPointerImplicitConversionCheck.cpp
78
BranchCloneCheck.cpp
89
BugproneTidyModule.cpp

clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../ClangTidyModule.h"
1111
#include "../ClangTidyModuleRegistry.h"
1212
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
13+
#include "../bugprone/BadSignalToKillThreadCheck.h"
1314
#include "../google/UnnamedNamespaceInHeaderCheck.h"
1415
#include "../misc/NewDeleteOverloadsCheck.h"
1516
#include "../misc/NonCopyableObjects.h"
@@ -82,6 +83,9 @@ class CERTModule : public ClangTidyModule {
8283
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
8384
CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
8485
"cert-msc32-c");
86+
// POS
87+
CheckFactories.registerCheck<bugprone::BadSignalToKillThreadCheck>(
88+
"cert-pos44-c");
8589
}
8690

8791
ClangTidyOptions getModuleOptions() override {

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ The improvements are...
6767
Improvements to clang-tidy
6868
--------------------------
6969

70+
- New :doc:`bugprone-bad-signal-to-kill-thread
71+
<clang-tidy/checks/bugprone-bad-signal-to-kill-thread>` check.
72+
73+
Finds ``pthread_kill`` function calls when a thread is terminated by
74+
raising ``SIGTERM`` signal.
75+
7076
- New :doc:`bugprone-dynamic-static-initializers
7177
<clang-tidy/checks/bugprone-dynamic-static-initializers>` check.
7278

@@ -88,6 +94,11 @@ Improvements to clang-tidy
8894
Without the null terminator it can result in undefined behaviour when the
8995
string is read.
9096

97+
- New alias :doc:`cert-pos44-cpp
98+
<clang-tidy/checks/cert-pos44-cpp>` to
99+
:doc:`bugprone-bad-signal-to-kill-thread
100+
<clang-tidy/checks/bugprone-bad-signal-to-kill-thread>` was added.
101+
91102
- New :doc:`cppcoreguidelines-init-variables
92103
<clang-tidy/checks/cppcoreguidelines-init-variables>` check.
93104

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.. title:: clang-tidy - bugprone-bad-signal-to-kill-thread
2+
3+
bugprone-bad-signal-to-kill-thread
4+
==================================
5+
6+
Finds ``pthread_kill`` function calls when a thread is terminated by
7+
raising ``SIGTERM`` signal and the signal kills the entire process, not
8+
just the individual thread. Use any signal except ``SIGTERM``.
9+
10+
.. code-block: c++
11+
12+
pthread_kill(thread, SIGTERM);
13+
14+
This check corresponds to the CERT C Coding Standard rule
15+
`POS44-C. Do not use signals to terminate threads
16+
<https://wiki.sei.cmu.edu/confluence/display/c/POS44-C.+Do+not+use+signals+to+terminate+threads>`_.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. title:: clang-tidy - cert-pos44-c
2+
.. meta::
3+
:http-equiv=refresh: 5;URL=bugprone-bad-signal-to-kill-thread.html
4+
5+
cert-pos44-c
6+
============
7+
8+
The cert-pos44-c check is an alias, please see
9+
`bugprone-bad-signal-to-kill-thread <bugprone-bad-signal-to-kill-thread.html>`_ for more information.

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Clang-Tidy Checks
3939
boost-use-to-string
4040
bugprone-argument-comment
4141
bugprone-assert-side-effect
42+
bugprone-bad-signal-to-kill-thread
4243
bugprone-bool-pointer-implicit-conversion
4344
bugprone-branch-clone
4445
bugprone-copy-constructor-init
@@ -105,6 +106,7 @@ Clang-Tidy Checks
105106
cert-msc51-cpp
106107
cert-oop11-cpp (redirects to performance-move-constructor-init) <cert-oop11-cpp>
107108
cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) <cert-oop54-cpp>
109+
cert-pos44-c (redirects to bugprone-bad-signal-to-kill-thread) <cert-pos44-c>
108110
clang-analyzer-core.CallAndMessage (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.CallAndMessage>
109111
clang-analyzer-core.DivideZero (redirects to https://clang.llvm.org/docs/analyzer/checkers) <clang-analyzer-core.DivideZero>
110112
clang-analyzer-core.DynamicTypePropagation
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %check_clang_tidy %s bugprone-bad-signal-to-kill-thread %t
2+
3+
#define SIGTERM 15
4+
#define SIGINT 2
5+
using pthread_t = int;
6+
using pthread_attr_t = int;
7+
8+
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
9+
void *(*start_routine)(void *), void *arg);
10+
11+
int pthread_kill(pthread_t thread, int sig);
12+
13+
int pthread_cancel(pthread_t thread);
14+
15+
void *test_func_return_a_pointer(void *foo);
16+
17+
int main() {
18+
int result;
19+
pthread_t thread;
20+
21+
if ((result = pthread_create(&thread, nullptr, test_func_return_a_pointer, 0)) != 0) {
22+
}
23+
if ((result = pthread_kill(thread, SIGTERM)) != 0) {
24+
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: thread should not be terminated by raising the 'SIGTERM' signal [bugprone-bad-signal-to-kill-thread]
25+
}
26+
27+
//compliant solution
28+
if ((result = pthread_cancel(thread)) != 0) {
29+
}
30+
31+
if ((result = pthread_kill(thread, SIGINT)) != 0) {
32+
}
33+
if ((result = pthread_kill(thread, 0xF)) != 0) {
34+
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: thread should not be terminated by raising the 'SIGTERM' signal [bugprone-bad-signal-to-kill-thread]
35+
}
36+
37+
return 0;
38+
}

0 commit comments

Comments
 (0)