@@ -29,7 +29,9 @@ namespace {
29
29
class BlockInCriticalSectionChecker : public Checker <check::PostCall,
30
30
check::PreCall> {
31
31
32
- CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn;
32
+ CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn,
33
+ PthreadLockFn, PthreadTryLockFn, PthreadUnlockFn,
34
+ MtxLock, MtxTimedLock, MtxTryLock, MtxUnlock;
33
35
34
36
std::unique_ptr<BugType> BlockInCritSectionBugType;
35
37
@@ -40,6 +42,10 @@ class BlockInCriticalSectionChecker : public Checker<check::PostCall,
40
42
public:
41
43
BlockInCriticalSectionChecker ();
42
44
45
+ bool isBlockingFunction (const CallEvent &Call) const ;
46
+ bool isLockFunction (const CallEvent &Call) const ;
47
+ bool isUnlockFunction (const CallEvent &Call) const ;
48
+
43
49
void checkPreCall (const CallEvent &Call, CheckerContext &C) const ;
44
50
45
51
// / Process unlock.
@@ -55,34 +61,69 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned)
55
61
56
62
BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
57
63
: LockFn(" lock" ), UnlockFn(" unlock" ), SleepFn(" sleep" ), GetcFn(" getc" ),
58
- FgetsFn(" fgets" ), ReadFn(" read" ), RecvFn(" recv" ) {
64
+ FgetsFn(" fgets" ), ReadFn(" read" ), RecvFn(" recv" ),
65
+ PthreadLockFn(" pthread_mutex_lock" ),
66
+ PthreadTryLockFn(" pthread_mutex_trylock" ),
67
+ PthreadUnlockFn(" pthread_mutex_unlock" ),
68
+ MtxLock(" mtx_lock" ),
69
+ MtxTimedLock(" mtx_timedlock" ),
70
+ MtxTryLock(" mtx_trylock" ),
71
+ MtxUnlock(" mtx_unlock" ) {
59
72
// Initialize the bug type.
60
73
BlockInCritSectionBugType.reset (
61
74
new BugType (this , " Call to blocking function in critical section" ,
62
75
" Blocking Error" ));
63
76
}
64
77
78
+ bool BlockInCriticalSectionChecker::isBlockingFunction (const CallEvent &Call) const {
79
+ if (Call.isCalled (SleepFn)
80
+ || Call.isCalled (GetcFn)
81
+ || Call.isCalled (FgetsFn)
82
+ || Call.isCalled (ReadFn)
83
+ || Call.isCalled (RecvFn)) {
84
+ return true ;
85
+ }
86
+ return false ;
87
+ }
88
+
89
+ bool BlockInCriticalSectionChecker::isLockFunction (const CallEvent &Call) const {
90
+ if (Call.isCalled (LockFn)
91
+ || Call.isCalled (PthreadLockFn)
92
+ || Call.isCalled (PthreadTryLockFn)
93
+ || Call.isCalled (MtxLock)
94
+ || Call.isCalled (MtxTimedLock)
95
+ || Call.isCalled (MtxTryLock)) {
96
+ return true ;
97
+ }
98
+ return false ;
99
+ }
100
+
101
+ bool BlockInCriticalSectionChecker::isUnlockFunction (const CallEvent &Call) const {
102
+ if (Call.isCalled (UnlockFn)
103
+ || Call.isCalled (PthreadUnlockFn)
104
+ || Call.isCalled (MtxUnlock)) {
105
+ return true ;
106
+ }
107
+ return false ;
108
+ }
109
+
65
110
void BlockInCriticalSectionChecker::checkPreCall (const CallEvent &Call,
66
111
CheckerContext &C) const {
67
112
}
68
113
69
114
void BlockInCriticalSectionChecker::checkPostCall (const CallEvent &Call,
70
115
CheckerContext &C) const {
71
- if (!Call.isCalled (LockFn)
72
- && !Call.isCalled (SleepFn)
73
- && !Call.isCalled (GetcFn)
74
- && !Call.isCalled (FgetsFn)
75
- && !Call.isCalled (ReadFn)
76
- && !Call.isCalled (RecvFn)
77
- && !Call.isCalled (UnlockFn))
116
+ if (!isBlockingFunction (Call)
117
+ && !isLockFunction (Call)
118
+ && !isUnlockFunction (Call))
78
119
return ;
79
120
80
121
ProgramStateRef State = C.getState ();
81
122
unsigned mutexCount = State->get <MutexCounter>();
82
- if (Call. isCalled (UnlockFn ) && mutexCount > 0 ) {
123
+ if (isUnlockFunction (Call ) && mutexCount > 0 ) {
83
124
State = State->set <MutexCounter>(--mutexCount);
84
125
C.addTransition (State);
85
- } else if (Call. isCalled (LockFn )) {
126
+ } else if (isLockFunction (Call )) {
86
127
State = State->set <MutexCounter>(++mutexCount);
87
128
C.addTransition (State);
88
129
} else if (mutexCount > 0 ) {
@@ -97,8 +138,11 @@ void BlockInCriticalSectionChecker::reportBlockInCritSection(
97
138
if (!ErrNode)
98
139
return ;
99
140
100
- auto R = llvm::make_unique<BugReport>(*BlockInCritSectionBugType,
101
- " A blocking function %s is called inside a critical section." , ErrNode);
141
+ std::string msg;
142
+ llvm::raw_string_ostream os (msg);
143
+ os << " Call to blocking function '" << Call.getCalleeIdentifier ()->getName ()
144
+ << " ' inside of critical section" ;
145
+ auto R = llvm::make_unique<BugReport>(*BlockInCritSectionBugType, os.str (), ErrNode);
102
146
R->addRange (Call.getSourceRange ());
103
147
R->markInteresting (BlockDescSym);
104
148
C.emitReport (std::move (R));
0 commit comments