Skip to content

[clang][analyzer][NFC] Add test for a limitation of alpha.unix.Bloc… #93799

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3148,6 +3148,22 @@ Applies to: ``lock, unlock, sleep, getc, fgets, read, recv, pthread_mutex_lock,`
m.unlock();
}

**Limitations**

* The ``trylock`` and ``timedlock`` versions of acquiring locks are currently assumed to always succeed.
This can lead to false positives.

.. code-block:: c

void trylock_example(pthread_mutex_t *m) {
if (pthread_mutex_trylock(m) == 0) { // assume trylock always succeeds
sleep(10); // warn: Call to blocking function 'sleep' inside of critical section
pthread_mutex_unlock(m);
} else {
sleep(10); // false positive: Incorrect warning about blocking function inside critical section.
}
}

.. _alpha-unix-Chroot:

alpha.unix.Chroot (C)
Expand Down
31 changes: 24 additions & 7 deletions clang/test/Analysis/block-in-critical-section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ ssize_t read(int fd, void *buf, size_t count);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

struct pthread_mutex_t;
void pthread_mutex_lock(pthread_mutex_t *mutex);
void pthread_mutex_trylock(pthread_mutex_t *mutex);
void pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

struct mtx_t;
void mtx_lock(mtx_t *mutex);
void mtx_timedlock(mtx_t *mutex);
void mtx_trylock(mtx_t *mutex);
void mtx_unlock(mtx_t *mutex);
int mtx_lock(mtx_t *mutex);
int mtx_timedlock(mtx_t *mutex);
int mtx_trylock(mtx_t *mutex);
int mtx_unlock(mtx_t *mutex);

// global params for dummy function calls
FILE *stream;
Expand Down Expand Up @@ -292,3 +292,20 @@ void testBlockInCriticalSectionUniqueLockNested() {
testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}}
sleep(1); // no-warning
}

void testTrylockCurrentlyFalsePositive(pthread_mutex_t *m) {
// expected-note@+4 {{Assuming the condition is true}}
// expected-note@+3 {{Taking true branch}}
// expected-note@+2 {{Assuming the condition is false}}
// expected-note@+1 {{Taking false branch}}
if (pthread_mutex_trylock(m) == 0) { // expected-note 2 {{Entering critical section here}}
// FIXME: we are entering the critical section only in the true branch
sleep(10); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
pthread_mutex_unlock(m);
} else {
sleep(10); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
// expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}}
// FIXME: this is a false positive, the lock was not acquired
}
}
Loading