1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s void sleep(int x) {} namespace std { struct mutex { void lock() {} void unlock() {} }; template<typename T> struct lock_guard { lock_guard<T>(std::mutex) {} ~lock_guard<T>() {} }; template<typename T> struct unique_lock { unique_lock<T>(std::mutex) {} ~unique_lock<T>() {} }; template<typename T> struct not_real_lock { not_real_lock<T>(std::mutex) {} }; } void getc() {} void fgets() {} void read() {} void recv() {} void pthread_mutex_lock() {} void pthread_mutex_trylock() {} void pthread_mutex_unlock() {} void mtx_lock() {} void mtx_timedlock() {} void mtx_trylock() {} void mtx_unlock() {} void testBlockInCriticalSectionWithStdMutex() { std::mutex m; m.lock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} m.unlock(); } void testBlockInCriticalSectionWithPthreadMutex() { pthread_mutex_lock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} pthread_mutex_unlock(); pthread_mutex_trylock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} pthread_mutex_unlock(); } void testBlockInCriticalSectionC11Locks() { mtx_lock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} mtx_unlock(); mtx_timedlock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} mtx_unlock(); mtx_trylock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} mtx_unlock(); } void testBlockInCriticalSectionWithNestedMutexes() { std::mutex m, n, k; m.lock(); n.lock(); k.lock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} k.unlock(); sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} n.unlock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} m.unlock(); sleep(3); // no-warning } void f() { sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionInterProcedural() { std::mutex m; m.lock(); f(); m.unlock(); } void testBlockInCriticalSectionUnexpectedUnlock() { std::mutex m; m.unlock(); sleep(1); // no-warning m.lock(); sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionLockGuard() { std::mutex g_mutex; std::not_real_lock<std::mutex> not_real_lock(g_mutex); sleep(1); // no-warning std::lock_guard<std::mutex> lock(g_mutex); sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionLockGuardNested() { testBlockInCriticalSectionLockGuard(); sleep(1); // no-warning } void testBlockInCriticalSectionUniqueLock() { std::mutex g_mutex; std::not_real_lock<std::mutex> not_real_lock(g_mutex); sleep(1); // no-warning std::unique_lock<std::mutex> lock(g_mutex); sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionUniqueLockNested() { testBlockInCriticalSectionUniqueLock(); sleep(1); // no-warning } |