[clang][analyzer] Teach the BlockInCriticalSectionChecker about O_NONBLOCK streams by flovent · Pull Request #127049 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-static-analyzer-1

Author: None (flovent)

Changes

this PR close #124474
when calling read and recv function for a non-block file descriptor or a invalid file descriptor(-1), it will not cause block inside a critical section.
this commit checks for non-block file descriptor assigned by open function with O_NONBLOCK flag.


Full diff: https://github.com/llvm/llvm-project/pull/127049.diff

2 Files Affected:

diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp index 7460781799d08..db784f2cc77b2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp @@ -145,7 +145,8 @@ using MutexDescriptor = std::variant<FirstArgMutexDescriptor, MemberMutexDescriptor, RAIIMutexDescriptor>;

-class BlockInCriticalSectionChecker : public Checkercheck::PostCall { +class BlockInCriticalSectionChecker

private: const std::array<MutexDescriptor, 8> MutexDescriptors{ // NOTE: There are standard library implementations where some methods @@ -179,6 +180,8 @@ class BlockInCriticalSectionChecker : public Checkercheck::PostCall { {CDM::CLibrary, {"read"}}, {CDM::CLibrary, {"recv"}}};

@@ -197,6 +200,8 @@ class BlockInCriticalSectionChecker : public Checkercheck::PostCall { void handleUnlock(const MutexDescriptor &Mutex, const CallEvent &Call, CheckerContext &C) const;

@@ -205,11 +210,14 @@ class BlockInCriticalSectionChecker : public Checkercheck::PostCall { /// Process lock. /// Process blocking functions (sleep, getc, fgets, read, recv) void checkPostCall(const CallEvent &Call, CheckerContext &C) const; +

} // end anonymous namespace

REGISTER_LIST_WITH_PROGRAMSTATE(ActiveCritSections, CritSectionMarker) +REGISTER_SET_WITH_PROGRAMSTATE(NonBlockFileDescriptor, SymbolRef)

// Iterator traits for ImmutableList data structure // that enable the use of STL algorithms. @@ -306,6 +314,25 @@ void BlockInCriticalSectionChecker::handleUnlock( C.addTransition(State); }

+void BlockInCriticalSectionChecker::handleOpen(const CallEvent &Call,

+} + bool BlockInCriticalSectionChecker::isBlockingInCritSection( const CallEvent &Call, CheckerContext &C) const { return BlockingFunctions.contains(Call) && @@ -315,6 +342,27 @@ bool BlockInCriticalSectionChecker::isBlockingInCritSection( void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { if (isBlockingInCritSection(Call, C)) {

@@ -322,9 +370,26 @@ void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call, } else if (std::optional UnlockDesc = checkDescriptorMatch(Call, C, /IsLock=/false)) { handleUnlock(*UnlockDesc, Call, C);

} }

+void BlockInCriticalSectionChecker::checkDeadSymbols(SymbolReaper &SymReaper,

+# define O_NONBLOCK 04000 + +void foo() +{

+}