https://github.com/gamesh411 updated https://github.com/llvm/llvm-project/pull/80029
From f7875a7f1ff20f3cf850ce1c23bec6d6c3d88d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fu...@sigmatechnology.com> Date: Tue, 30 Jan 2024 11:33:30 +0100 Subject: [PATCH] [clang][analyzer] Add note tags to alpha.unix.BlockInCriticalSection checker On entering a critical section, a note tag is now placed along the bugpath. --- .../BlockInCriticalSectionChecker.cpp | 18 ++++- .../Analysis/block-in-critical-section.cpp | 77 ++++++++++++++----- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp index 66e080adb1382..1297ae96c8b64 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp @@ -57,6 +57,8 @@ class BlockInCriticalSectionChecker : public Checker<check::PostCall> { const CallEvent &call, CheckerContext &C) const; + const NoteTag *createCriticalSectionNote(CheckerContext &C) const; + public: bool isBlockingFunction(const CallEvent &Call) const; bool isLockFunction(const CallEvent &Call) const; @@ -126,8 +128,9 @@ void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call, State = State->set<MutexCounter>(--mutexCount); C.addTransition(State); } else if (isLockFunction(Call)) { + const NoteTag *Note = createCriticalSectionNote(C); State = State->set<MutexCounter>(++mutexCount); - C.addTransition(State); + C.addTransition(State, Note); } else if (mutexCount > 0) { SymbolRef BlockDesc = Call.getReturnValue().getAsSymbol(); reportBlockInCritSection(BlockDesc, Call, C); @@ -151,10 +154,21 @@ void BlockInCriticalSectionChecker::reportBlockInCritSection( C.emitReport(std::move(R)); } +const NoteTag *BlockInCriticalSectionChecker::createCriticalSectionNote( + CheckerContext &C) const { + const BugType *BT = &this->BlockInCritSectionBugType; + return C.getNoteTag([BT](PathSensitiveBugReport &BR, llvm::raw_ostream &OS) { + if (&BR.getBugType() != BT) + return; + OS << "Entering critical section here"; + }); +} + void ento::registerBlockInCriticalSectionChecker(CheckerManager &mgr) { mgr.registerChecker<BlockInCriticalSectionChecker>(); } -bool ento::shouldRegisterBlockInCriticalSectionChecker(const CheckerManager &mgr) { +bool ento::shouldRegisterBlockInCriticalSectionChecker( + const CheckerManager &mgr) { return true; } diff --git a/clang/test/Analysis/block-in-critical-section.cpp b/clang/test/Analysis/block-in-critical-section.cpp index fcf6188fc033e..93d46c741e16f 100644 --- a/clang/test/Analysis/block-in-critical-section.cpp +++ b/clang/test/Analysis/block-in-critical-section.cpp @@ -1,4 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=alpha.unix.BlockInCriticalSection \ +// RUN: -std=c++11 \ +// RUN: -analyzer-output text \ +// RUN: -verify %s void sleep(int x) {} @@ -21,7 +25,7 @@ template<typename T> struct not_real_lock { not_real_lock<T>(std::mutex) {} }; -} +} // namespace std void getc() {} void fgets() {} @@ -39,81 +43,115 @@ void mtx_unlock() {} void testBlockInCriticalSectionWithStdMutex() { std::mutex m; - m.lock(); + m.lock(); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} m.unlock(); } void testBlockInCriticalSectionWithPthreadMutex() { - pthread_mutex_lock(); + pthread_mutex_lock(); // expected-note 10{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} pthread_mutex_unlock(); - pthread_mutex_trylock(); + pthread_mutex_trylock(); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} pthread_mutex_unlock(); } void testBlockInCriticalSectionC11Locks() { - mtx_lock(); + mtx_lock(); // expected-note 15{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} mtx_unlock(); - mtx_timedlock(); + mtx_timedlock(); // expected-note 10{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} mtx_unlock(); - mtx_trylock(); + mtx_trylock(); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} mtx_unlock(); } void testBlockInCriticalSectionWithNestedMutexes() { std::mutex m, n, k; - m.lock(); - n.lock(); - k.lock(); + m.lock(); // expected-note 3{{Entering critical section here}} + n.lock(); // expected-note 3{{Entering critical section here}} + k.lock(); // expected-note 3{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} k.unlock(); sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} n.unlock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{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}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionInterProcedural() { std::mutex m; - m.lock(); - f(); + m.lock(); // expected-note {{Entering critical section here}} + f(); // expected-note {{Calling 'f'}} m.unlock(); } @@ -121,8 +159,9 @@ void testBlockInCriticalSectionUnexpectedUnlock() { std::mutex m; m.unlock(); sleep(1); // no-warning - m.lock(); + m.lock(); // expected-note {{Entering critical section here}} sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionLockGuard() { @@ -130,12 +169,13 @@ void testBlockInCriticalSectionLockGuard() { std::not_real_lock<std::mutex> not_real_lock(g_mutex); sleep(1); // no-warning - std::lock_guard<std::mutex> lock(g_mutex); + std::lock_guard<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}} sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionLockGuardNested() { - testBlockInCriticalSectionLockGuard(); + testBlockInCriticalSectionLockGuard(); // expected-note {{Calling 'testBlockInCriticalSectionLockGuard'}} sleep(1); // no-warning } @@ -144,11 +184,12 @@ void testBlockInCriticalSectionUniqueLock() { std::not_real_lock<std::mutex> not_real_lock(g_mutex); sleep(1); // no-warning - std::unique_lock<std::mutex> lock(g_mutex); + std::unique_lock<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}} sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionUniqueLockNested() { - testBlockInCriticalSectionUniqueLock(); + testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}} sleep(1); // no-warning } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits