321 lines · cpp
1// RUN: %clang_analyze_cc1 \2// RUN: -analyzer-checker=unix.BlockInCriticalSection \3// RUN: -std=c++11 \4// RUN: -analyzer-output text \5// RUN: -verify %s6 7void sleep(int x) {}8 9namespace std {10struct mutex {11 void lock() {}12 void unlock() {}13};14template<typename T>15struct lock_guard {16 lock_guard<T>(std::mutex) {}17 ~lock_guard<T>() {}18};19struct defer_lock_t {};20constexpr defer_lock_t defer_lock{};21template<typename T>22struct unique_lock {23 unique_lock<T>(std::mutex) {}24 unique_lock<T>(std::mutex, defer_lock_t) {} // defer_lock parameter25 ~unique_lock<T>() {}26};27template<typename T>28struct not_real_lock {29 not_real_lock<T>(std::mutex) {}30};31} // namespace std32 33struct FILE;34int getc(FILE *stream);35char* fgets(char *str, FILE *stream);36using ssize_t = long long;37using size_t = unsigned long long;38ssize_t read(int fd, void *buf, size_t count);39ssize_t recv(int sockfd, void *buf, size_t len, int flags);40 41struct pthread_mutex_t;42int pthread_mutex_lock(pthread_mutex_t *mutex);43int pthread_mutex_trylock(pthread_mutex_t *mutex);44int pthread_mutex_unlock(pthread_mutex_t *mutex);45 46struct mtx_t;47int mtx_lock(mtx_t *mutex);48int mtx_timedlock(mtx_t *mutex);49int mtx_trylock(mtx_t *mutex);50int mtx_unlock(mtx_t *mutex);51 52// global params for dummy function calls53FILE *stream;54char *str;55int fd;56void *buf;57size_t count;58int sockfd;59size_t len;60int flags;61 62void testBlockInCriticalSectionWithStdMutex() {63 std::mutex m;64 m.lock(); // expected-note 5{{Entering critical section here}}65 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}66 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}67 getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}}68 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}69 fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}70 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}71 read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}}72 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}73 recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}}74 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}75 m.unlock();76}77 78void testBlockInCriticalSectionWithPthreadMutex(pthread_mutex_t *mutex) {79 pthread_mutex_lock(mutex); // expected-note 5{{Entering critical section here}}80 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}81 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}82 getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}}83 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}84 fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}85 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}86 read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}}87 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}88 recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}}89 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}90 pthread_mutex_unlock(mutex);91 92 pthread_mutex_trylock(mutex); // expected-note 5{{Entering critical section here}}93 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}94 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}95 getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}}96 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}97 fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}98 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}99 read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}}100 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}101 recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}}102 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}103 pthread_mutex_unlock(mutex);104}105 106void testBlockInCriticalSectionC11Locks(mtx_t *mutex) {107 mtx_lock(mutex); // expected-note 5{{Entering critical section here}}108 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}109 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}110 getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}}111 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}112 fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}113 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}114 read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}}115 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}116 recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}}117 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}118 mtx_unlock(mutex);119 120 mtx_timedlock(mutex); // expected-note 5{{Entering critical section here}}121 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}122 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}123 getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}}124 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}125 fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}126 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}127 read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}}128 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}129 recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}}130 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}131 mtx_unlock(mutex);132 133 mtx_trylock(mutex); // expected-note 5{{Entering critical section here}}134 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}135 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}136 getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}}137 // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}}138 fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}139 // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}}140 read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}}141 // expected-note@-1 {{Call to blocking function 'read' inside of critical section}}142 recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}}143 // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}}144 mtx_unlock(mutex);145}146 147void testMultipleBlockingCalls() {148 std::mutex m;149 m.lock(); // expected-note 1{{Entering critical section here}}150 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}151 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}152 m.unlock();153 sleep(2); // no-warning154}155 156void testMultipleMutexesMultipleBlockingCalls() {157 std::mutex m, n, k;158 m.lock(); // expected-note 2{{Entering critical section here}}159 n.lock(); // expected-note 2{{Entering critical section here}}160 k.lock(); // expected-note 1{{Entering critical section here}}161 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}162 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}163 k.unlock();164 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}165 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}166}167 168 169void testRecursiveAcquisition() {170 std::mutex m;171 m.lock(); // expected-note {{Entering critical section for the 1st time here}}172 m.lock(); // expected-note {{Entering critical section for the 2nd time here}}173 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}174 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}175 m.unlock();176 m.unlock();177}178 179void testRecursiveAcquisitionWithMultipleBlockingCalls() {180 std::mutex m;181 m.lock(); // expected-note 1{{Entering critical section for the 1st time here}}182 // expected-note@-1 {{Entering critical section here}}183 m.lock(); // expected-note 1{{Entering critical section for the 2nd time here}}184 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}185 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}186 m.unlock();187 // this next 'sleep' call is only in the critical section of the first lock188 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}189 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}190 m.unlock();191}192 193void testRecursiveAcquisitionWithMultipleMutexes() {194 std::mutex m, n;195 m.lock(); // expected-note 1{{Entering critical section here}}196 n.lock(); // expected-note 2{{Entering critical section here}}197 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}198 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}199 m.unlock();200 // this next 'sleep' call is only in the critical section of mutex 'n'201 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}202 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}203 n.unlock();204}205 206 207void testNestedMutexes() {208 std::mutex m, n, k;209 m.lock(); // expected-note 3{{Entering critical section here}}210 n.lock(); // expected-note 2{{Entering critical section here}}211 k.lock(); // expected-note 1{{Entering critical section here}}212 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}213 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}214 k.unlock();215 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}216 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}217 n.unlock();218 sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}219 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}220 m.unlock();221 sleep(4); // no-warning222}223 224void testNonOverlappingMutexes() {225 std::mutex m;226 m.lock(); // There should be no warning here227 m.unlock();228 m.lock(); // expected-note {{Entering critical section here}}229 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}230 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}231 m.unlock();232}233 234void testMixedMutexLocksWithIntermittentUnlock() {235 std::mutex m, n, k;236 m.lock(); // expected-note {{Entering critical section here}}237 n.lock(); // the problem is not is this lock's critical section238 n.unlock();239 k.lock(); // same as for n.lock()240 k.unlock();241 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}242 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}243 m.unlock();244}245 246void f() {247 sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}248 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}249}250 251void testBlockInCriticalSectionInterProcedural() {252 std::mutex m;253 m.lock(); // expected-note {{Entering critical section here}}254 f(); // expected-note {{Calling 'f'}}255 m.unlock();256}257 258void unknown_function_that_may_lock(std::mutex &);259void testBlockInCriticalSectionUnexpectedUnlock() {260 std::mutex m;261 unknown_function_that_may_lock(m);262 m.unlock();263 sleep(1); // no-warning264 m.lock(); // expected-note {{Entering critical section here}}265 sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}266 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}267}268 269void testBlockInCriticalSectionLockGuard() {270 std::mutex g_mutex;271 std::not_real_lock<std::mutex> not_real_lock(g_mutex);272 sleep(1); // no-warning273 274 std::lock_guard<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}}275 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}276 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}277}278 279void testBlockInCriticalSectionLockGuardNested() {280 testBlockInCriticalSectionLockGuard(); // expected-note {{Calling 'testBlockInCriticalSectionLockGuard'}}281 sleep(1); // no-warning282}283 284void testBlockInCriticalSectionUniqueLock() {285 std::mutex g_mutex;286 std::not_real_lock<std::mutex> not_real_lock(g_mutex);287 sleep(1); // no-warning288 289 std::unique_lock<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}}290 sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}291 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}292}293 294void testBlockInCriticalSectionUniqueLockNested() {295 testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}}296 sleep(1); // no-warning297}298 299void testTrylockCurrentlyFalsePositive(pthread_mutex_t *m) {300 // expected-note@+4 {{Assuming the condition is true}}301 // expected-note@+3 {{Taking true branch}}302 // expected-note@+2 {{Assuming the condition is false}}303 // expected-note@+1 {{Taking false branch}}304 if (pthread_mutex_trylock(m) == 0) { // expected-note 2 {{Entering critical section here}}305 // FIXME: we are entering the critical section only in the true branch306 sleep(10); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}307 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}308 pthread_mutex_unlock(m);309 } else {310 sleep(10); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}311 // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}312 // FIXME: this is a false positive, the lock was not acquired313 }314}315 316void testBlockInCriticalSectionUniqueLockWithDeferLock() {317 std::mutex g_mutex;318 std::unique_lock<std::mutex> lock(g_mutex, std::defer_lock);319 sleep(1); // no-warning320}321