1 // RUN: %clang_analyze_cc1 \
2 // RUN: -analyzer-checker=unix.BlockInCriticalSection \
4 // RUN: -analyzer-output text \
16 lock_guard
<T
>(std::mutex
) {}
21 unique_lock
<T
>(std::mutex
) {}
25 struct not_real_lock
{
26 not_real_lock
<T
>(std::mutex
) {}
31 int getc(FILE *stream
);
32 char* fgets(char *str
, FILE *stream
);
33 using ssize_t
= long long;
34 using size_t = unsigned long long;
35 ssize_t
read(int fd
, void *buf
, size_t count
);
36 ssize_t
recv(int sockfd
, void *buf
, size_t len
, int flags
);
38 struct pthread_mutex_t
;
39 int pthread_mutex_lock(pthread_mutex_t
*mutex
);
40 int pthread_mutex_trylock(pthread_mutex_t
*mutex
);
41 int pthread_mutex_unlock(pthread_mutex_t
*mutex
);
44 int mtx_lock(mtx_t
*mutex
);
45 int mtx_timedlock(mtx_t
*mutex
);
46 int mtx_trylock(mtx_t
*mutex
);
47 int mtx_unlock(mtx_t
*mutex
);
49 // global params for dummy function calls
59 void testBlockInCriticalSectionWithStdMutex() {
61 m
.lock(); // expected-note 5{{Entering critical section here}}
62 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
63 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
64 getc(stream
); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
65 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
66 fgets(str
, stream
); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
67 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
68 read(fd
, buf
, count
); // expected-warning {{Call to blocking function 'read' inside of critical section}}
69 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
70 recv(sockfd
, buf
, count
, flags
); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
71 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
75 void testBlockInCriticalSectionWithPthreadMutex(pthread_mutex_t
*mutex
) {
76 pthread_mutex_lock(mutex
); // expected-note 5{{Entering critical section here}}
77 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
78 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
79 getc(stream
); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
80 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
81 fgets(str
, stream
); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
82 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
83 read(fd
, buf
, count
); // expected-warning {{Call to blocking function 'read' inside of critical section}}
84 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
85 recv(sockfd
, buf
, count
, flags
); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
86 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
87 pthread_mutex_unlock(mutex
);
89 pthread_mutex_trylock(mutex
); // expected-note 5{{Entering critical section here}}
90 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
91 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
92 getc(stream
); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
93 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
94 fgets(str
, stream
); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
95 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
96 read(fd
, buf
, count
); // expected-warning {{Call to blocking function 'read' inside of critical section}}
97 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
98 recv(sockfd
, buf
, count
, flags
); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
99 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
100 pthread_mutex_unlock(mutex
);
103 void testBlockInCriticalSectionC11Locks(mtx_t
*mutex
) {
104 mtx_lock(mutex
); // expected-note 5{{Entering critical section here}}
105 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
106 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
107 getc(stream
); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
108 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
109 fgets(str
, stream
); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
110 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
111 read(fd
, buf
, count
); // expected-warning {{Call to blocking function 'read' inside of critical section}}
112 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
113 recv(sockfd
, buf
, count
, flags
); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
114 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
117 mtx_timedlock(mutex
); // expected-note 5{{Entering critical section here}}
118 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
119 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
120 getc(stream
); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
121 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
122 fgets(str
, stream
); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
123 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
124 read(fd
, buf
, count
); // expected-warning {{Call to blocking function 'read' inside of critical section}}
125 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
126 recv(sockfd
, buf
, count
, flags
); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
127 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
130 mtx_trylock(mutex
); // expected-note 5{{Entering critical section here}}
131 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
132 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
133 getc(stream
); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
134 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}
135 fgets(str
, stream
); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
136 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}
137 read(fd
, buf
, count
); // expected-warning {{Call to blocking function 'read' inside of critical section}}
138 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}
139 recv(sockfd
, buf
, count
, flags
); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
140 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}
144 void testMultipleBlockingCalls() {
146 m
.lock(); // expected-note 1{{Entering critical section here}}
147 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
148 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
150 sleep(2); // no-warning
153 void testMultipleMutexesMultipleBlockingCalls() {
155 m
.lock(); // expected-note 2{{Entering critical section here}}
156 n
.lock(); // expected-note 2{{Entering critical section here}}
157 k
.lock(); // expected-note 1{{Entering critical section here}}
158 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
159 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
161 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
162 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
166 void testRecursiveAcquisition() {
168 m
.lock(); // expected-note {{Entering critical section for the 1st time here}}
169 m
.lock(); // expected-note {{Entering critical section for the 2nd time here}}
170 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
171 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
176 void testRecursiveAcquisitionWithMultipleBlockingCalls() {
178 m
.lock(); // expected-note 1{{Entering critical section for the 1st time here}}
179 // expected-note@-1 {{Entering critical section here}}
180 m
.lock(); // expected-note 1{{Entering critical section for the 2nd time here}}
181 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
182 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
184 // this next 'sleep' call is only in the critical section of the first lock
185 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
186 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
190 void testRecursiveAcquisitionWithMultipleMutexes() {
192 m
.lock(); // expected-note 1{{Entering critical section here}}
193 n
.lock(); // expected-note 2{{Entering critical section here}}
194 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
195 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
197 // this next 'sleep' call is only in the critical section of mutex 'n'
198 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
199 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
204 void testNestedMutexes() {
206 m
.lock(); // expected-note 3{{Entering critical section here}}
207 n
.lock(); // expected-note 2{{Entering critical section here}}
208 k
.lock(); // expected-note 1{{Entering critical section here}}
209 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
210 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
212 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
213 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
215 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
216 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
218 sleep(4); // no-warning
221 void testNonOverlappingMutexes() {
223 m
.lock(); // There should be no warning here
225 m
.lock(); // expected-note {{Entering critical section here}}
226 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
227 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
231 void testMixedMutexLocksWithIntermittentUnlock() {
233 m
.lock(); // expected-note {{Entering critical section here}}
234 n
.lock(); // the problem is not is this lock's critical section
236 k
.lock(); // same as for n.lock()
238 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
239 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
244 sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
245 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
248 void testBlockInCriticalSectionInterProcedural() {
250 m
.lock(); // expected-note {{Entering critical section here}}
251 f(); // expected-note {{Calling 'f'}}
255 void unknown_function_that_may_lock(std::mutex
&);
256 void testBlockInCriticalSectionUnexpectedUnlock() {
258 unknown_function_that_may_lock(m
);
260 sleep(1); // no-warning
261 m
.lock(); // expected-note {{Entering critical section here}}
262 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
263 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
266 void testBlockInCriticalSectionLockGuard() {
268 std::not_real_lock
<std::mutex
> not_real_lock(g_mutex
);
269 sleep(1); // no-warning
271 std::lock_guard
<std::mutex
> lock(g_mutex
); // expected-note {{Entering critical section here}}
272 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
273 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
276 void testBlockInCriticalSectionLockGuardNested() {
277 testBlockInCriticalSectionLockGuard(); // expected-note {{Calling 'testBlockInCriticalSectionLockGuard'}}
278 sleep(1); // no-warning
281 void testBlockInCriticalSectionUniqueLock() {
283 std::not_real_lock
<std::mutex
> not_real_lock(g_mutex
);
284 sleep(1); // no-warning
286 std::unique_lock
<std::mutex
> lock(g_mutex
); // expected-note {{Entering critical section here}}
287 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
288 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
291 void testBlockInCriticalSectionUniqueLockNested() {
292 testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}}
293 sleep(1); // no-warning
296 void testTrylockCurrentlyFalsePositive(pthread_mutex_t
*m
) {
297 // expected-note@+4 {{Assuming the condition is true}}
298 // expected-note@+3 {{Taking true branch}}
299 // expected-note@+2 {{Assuming the condition is false}}
300 // expected-note@+1 {{Taking false branch}}
301 if (pthread_mutex_trylock(m
) == 0) { // expected-note 2 {{Entering critical section here}}
302 // FIXME: we are entering the critical section only in the true branch
303 sleep(10); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
304 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
305 pthread_mutex_unlock(m
);
307 sleep(10); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
308 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
309 // FIXME: this is a false positive, the lock was not acquired