cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
522 lines
12 KiB
C
522 lines
12 KiB
C
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.PthreadLock -verify %s
|
|
|
|
// Tests performing normal locking patterns and wrong locking orders
|
|
|
|
#include "Inputs/system-header-simulator-for-pthread-lock.h"
|
|
|
|
pthread_mutex_t mtx1, mtx2;
|
|
pthread_mutex_t *pmtx;
|
|
lck_mtx_t lck1, lck2;
|
|
lck_grp_t grp1;
|
|
lck_rw_t rw;
|
|
|
|
#define NULL 0
|
|
|
|
void
|
|
ok1(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok2(void)
|
|
{
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok3(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok4(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // no-warning
|
|
}
|
|
|
|
void
|
|
ok5(void)
|
|
{
|
|
if (pthread_mutex_trylock(&mtx1) == 0) // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok6(void)
|
|
{
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok7(void)
|
|
{
|
|
if (lck_mtx_try_lock(&lck1) != 0) // no-warning
|
|
lck_mtx_unlock(&lck1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok8(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok9(void)
|
|
{
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
if (pthread_mutex_trylock(&mtx1) == 0) // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok10(void)
|
|
{
|
|
if (pthread_mutex_trylock(&mtx1) != 0) // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok11(void)
|
|
{
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok12(void)
|
|
{
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx2); // no-warning
|
|
}
|
|
|
|
void
|
|
ok13(void)
|
|
{
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok14(void)
|
|
{
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // no-warning
|
|
pthread_mutex_destroy(&mtx2); // no-warning
|
|
}
|
|
|
|
void
|
|
ok15(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
}
|
|
|
|
void
|
|
ok16(void)
|
|
{
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
}
|
|
|
|
void
|
|
ok17(void)
|
|
{
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
pthread_mutex_init(&mtx2, NULL); // no-warning
|
|
}
|
|
|
|
void
|
|
ok18(void)
|
|
{
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
}
|
|
|
|
void
|
|
ok19(void)
|
|
{
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
pthread_mutex_destroy(&mtx2); // no-warning
|
|
pthread_mutex_init(&mtx2, NULL); // no-warning
|
|
}
|
|
|
|
void
|
|
ok20(void)
|
|
{
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
}
|
|
|
|
void
|
|
ok21(void) {
|
|
pthread_mutex_lock(pmtx); // no-warning
|
|
pthread_mutex_unlock(pmtx); // no-warning
|
|
}
|
|
|
|
void
|
|
ok22(void) {
|
|
pthread_mutex_lock(pmtx); // no-warning
|
|
pthread_mutex_unlock(pmtx); // no-warning
|
|
pthread_mutex_lock(pmtx); // no-warning
|
|
pthread_mutex_unlock(pmtx); // no-warning
|
|
}
|
|
|
|
void ok23(void) {
|
|
if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
}
|
|
|
|
void ok24(void) {
|
|
if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
}
|
|
|
|
void ok25(void) {
|
|
if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
}
|
|
|
|
void ok26(void) {
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
}
|
|
|
|
void ok27(void) {
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
else
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
}
|
|
|
|
void ok28(void) {
|
|
if (pthread_mutex_destroy(&mtx1) != 0) { // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
}
|
|
}
|
|
|
|
void ok29(void) {
|
|
lck_rw_lock_shared(&rw);
|
|
lck_rw_unlock_shared(&rw);
|
|
lck_rw_lock_exclusive(&rw); // no-warning
|
|
lck_rw_unlock_exclusive(&rw); // no-warning
|
|
}
|
|
|
|
void escape_mutex(pthread_mutex_t *m);
|
|
void ok30(void) {
|
|
pthread_mutex_t local_mtx;
|
|
pthread_mutex_init(&local_mtx, NULL);
|
|
pthread_mutex_lock(&local_mtx);
|
|
escape_mutex(&local_mtx);
|
|
pthread_mutex_lock(&local_mtx); // no-warning
|
|
pthread_mutex_unlock(&local_mtx);
|
|
pthread_mutex_destroy(&local_mtx);
|
|
}
|
|
|
|
void ok31(void) {
|
|
pthread_mutex_t local_mtx;
|
|
pthread_mutex_init(&local_mtx, NULL);
|
|
pthread_mutex_lock(&local_mtx);
|
|
fake_system_function_that_takes_a_mutex(&local_mtx);
|
|
pthread_mutex_lock(&local_mtx); // no-warning
|
|
pthread_mutex_unlock(&local_mtx);
|
|
pthread_mutex_destroy(&local_mtx);
|
|
}
|
|
|
|
void
|
|
bad1(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been acquired}}
|
|
}
|
|
|
|
void
|
|
bad2(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been acquired}}
|
|
}
|
|
|
|
void
|
|
bad3(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This was not the most recently acquired lock}}
|
|
pthread_mutex_unlock(&mtx2);
|
|
}
|
|
|
|
void
|
|
bad4(void)
|
|
{
|
|
if (pthread_mutex_trylock(&mtx1)) // no-warning
|
|
return;
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This was not the most recently acquired lock}}
|
|
}
|
|
|
|
void
|
|
bad5(void)
|
|
{
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
lck_mtx_lock(&lck1); // expected-warning{{This lock has already been acquired}}
|
|
}
|
|
|
|
void
|
|
bad6(void)
|
|
{
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
lck_mtx_unlock(&lck1); // no-warning
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
lck_mtx_lock(&lck1); // expected-warning{{This lock has already been acquired}}
|
|
}
|
|
|
|
void
|
|
bad7(void)
|
|
{
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
lck_mtx_lock(&lck2); // no-warning
|
|
lck_mtx_unlock(&lck1); // expected-warning{{This was not the most recently acquired lock}}
|
|
lck_mtx_unlock(&lck2);
|
|
}
|
|
|
|
void
|
|
bad8(void)
|
|
{
|
|
if (lck_mtx_try_lock(&lck1) == 0) // no-warning
|
|
return;
|
|
lck_mtx_lock(&lck2); // no-warning
|
|
lck_mtx_unlock(&lck1); // expected-warning{{This was not the most recently acquired lock}}
|
|
}
|
|
|
|
void
|
|
bad9(void)
|
|
{
|
|
lck_mtx_unlock(&lck1); // no-warning
|
|
lck_mtx_unlock(&lck1); // expected-warning{{This lock has already been unlocked}}
|
|
}
|
|
|
|
void
|
|
bad10(void)
|
|
{
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
lck_mtx_unlock(&lck1); // no-warning
|
|
lck_mtx_unlock(&lck1); // expected-warning{{This lock has already been unlocked}}
|
|
}
|
|
|
|
static void
|
|
bad11_sub(pthread_mutex_t *lock)
|
|
{
|
|
lck_mtx_unlock(lock); // expected-warning{{This lock has already been unlocked}}
|
|
}
|
|
|
|
void
|
|
bad11(int i)
|
|
{
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
lck_mtx_unlock(&lck1); // no-warning
|
|
if (i < 5)
|
|
bad11_sub(&lck1);
|
|
}
|
|
|
|
void
|
|
bad12(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This lock has already been unlocked}}
|
|
}
|
|
|
|
void
|
|
bad13(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This lock has already been unlocked}}
|
|
}
|
|
|
|
void
|
|
bad14(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // expected-warning{{This lock has already been unlocked}}
|
|
}
|
|
|
|
void
|
|
bad15(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx2); // expected-warning{{This lock has already been unlocked}}
|
|
}
|
|
|
|
void
|
|
bad16(void)
|
|
{
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void
|
|
bad17(void)
|
|
{
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void
|
|
bad18(void)
|
|
{
|
|
pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void
|
|
bad19(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_destroy(&mtx1); // expected-warning{{This lock is still locked}}
|
|
}
|
|
|
|
void
|
|
bad20(void)
|
|
{
|
|
lck_mtx_destroy(&mtx1, &grp1); // no-warning
|
|
lck_mtx_lock(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void
|
|
bad21(void)
|
|
{
|
|
lck_mtx_destroy(&mtx1, &grp1); // no-warning
|
|
lck_mtx_unlock(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void
|
|
bad22(void)
|
|
{
|
|
lck_mtx_destroy(&mtx1, &grp1); // no-warning
|
|
lck_mtx_destroy(&mtx1, &grp1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void
|
|
bad23(void)
|
|
{
|
|
lck_mtx_lock(&mtx1); // no-warning
|
|
lck_mtx_destroy(&mtx1, &grp1); // expected-warning{{This lock is still locked}}
|
|
}
|
|
|
|
void
|
|
bad24(void)
|
|
{
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock has already been initialized}}
|
|
}
|
|
|
|
void
|
|
bad25(void)
|
|
{
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock is still being held}}
|
|
}
|
|
|
|
void
|
|
bad26(void)
|
|
{
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock has already been initialized}}
|
|
}
|
|
|
|
void bad27(void) {
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
int ret = pthread_mutex_destroy(&mtx1); // no-warning
|
|
if (ret != 0) // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
else
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void bad28(void) {
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
int ret = pthread_mutex_destroy(&mtx1); // no-warning
|
|
if (ret != 0) // no-warning
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
else
|
|
pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void bad29(void) {
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock has already been initialized}}
|
|
else
|
|
pthread_mutex_init(&mtx1, NULL); // no-warning
|
|
}
|
|
|
|
void bad30(void) {
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
|
|
pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock has already been initialized}}
|
|
else
|
|
pthread_mutex_destroy(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
}
|
|
|
|
void bad31(void) {
|
|
int ret = pthread_mutex_destroy(&mtx1); // no-warning
|
|
pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been destroyed}}
|
|
if (ret != 0)
|
|
pthread_mutex_lock(&mtx1);
|
|
}
|
|
|
|
void bad32(void) {
|
|
lck_rw_lock_shared(&rw);
|
|
lck_rw_unlock_exclusive(&rw); // FIXME: warn - should be shared?
|
|
lck_rw_lock_exclusive(&rw);
|
|
lck_rw_unlock_shared(&rw); // FIXME: warn - should be exclusive?
|
|
}
|
|
|
|
void bad33(void) {
|
|
pthread_mutex_lock(pmtx);
|
|
fake_system_function();
|
|
pthread_mutex_lock(pmtx); // expected-warning{{This lock has already been acquired}}
|
|
}
|
|
|
|
void nocrash1(pthread_mutex_t *mutex) {
|
|
int ret = pthread_mutex_destroy(mutex);
|
|
if (ret == 0) // no crash
|
|
;
|
|
}
|