Skip to content

Commit 46b3145

Browse files
authored
[clang][analyzer][NFC] Add test for a limitation of alpha.unix.BlockInCriticalSection checker (#93799)
Updated the documentation in `checkers.rst` to include an example of how `trylock` function is handled. Added a new test for a scenario where `pthread_mutex_trylock` is used, demonstrating the current limitation.
1 parent 196dca7 commit 46b3145

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3157,6 +3157,22 @@ Critical section handling functions modelled by this checker: ``lock, unlock, pt
31573157
// still inside of the critical section of the std::lock_guard
31583158
}
31593159
3160+
**Limitations**
3161+
3162+
* The ``trylock`` and ``timedlock`` versions of acquiring locks are currently assumed to always succeed.
3163+
This can lead to false positives.
3164+
3165+
.. code-block:: c
3166+
3167+
void trylock_example(pthread_mutex_t *m) {
3168+
if (pthread_mutex_trylock(m) == 0) { // assume trylock always succeeds
3169+
sleep(10); // warn: Call to blocking function 'sleep' inside of critical section
3170+
pthread_mutex_unlock(m);
3171+
} else {
3172+
sleep(10); // false positive: Incorrect warning about blocking function inside critical section.
3173+
}
3174+
}
3175+
31603176
.. _alpha-unix-Chroot:
31613177
31623178
alpha.unix.Chroot (C)

clang/test/Analysis/block-in-critical-section.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ ssize_t read(int fd, void *buf, size_t count);
3636
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
3737

3838
struct pthread_mutex_t;
39-
void pthread_mutex_lock(pthread_mutex_t *mutex);
40-
void pthread_mutex_trylock(pthread_mutex_t *mutex);
41-
void pthread_mutex_unlock(pthread_mutex_t *mutex);
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);
4242

4343
struct mtx_t;
44-
void mtx_lock(mtx_t *mutex);
45-
void mtx_timedlock(mtx_t *mutex);
46-
void mtx_trylock(mtx_t *mutex);
47-
void mtx_unlock(mtx_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);
4848

4949
// global params for dummy function calls
5050
FILE *stream;
@@ -292,3 +292,20 @@ void testBlockInCriticalSectionUniqueLockNested() {
292292
testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}}
293293
sleep(1); // no-warning
294294
}
295+
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);
306+
} else {
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
310+
}
311+
}

0 commit comments

Comments
 (0)