Skip to content

Commit 20bec01

Browse files
committed
update based on review advice
1 parent f2f9287 commit 20bec01

File tree

3 files changed

+54
-47
lines changed

3 files changed

+54
-47
lines changed

clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ class BlockInCriticalSectionChecker
185185
const BugType BlockInCritSectionBugType{
186186
this, "Call to blocking function in critical section", "Blocking Error"};
187187

188+
using O_NONBLOCKValueTy = std::optional<int>;
189+
mutable std::optional<O_NONBLOCKValueTy> O_NONBLOCKValue;
190+
188191
void reportBlockInCritSection(const CallEvent &call, CheckerContext &C) const;
189192

190193
[[nodiscard]] const NoteTag *createCritSectionNote(CritSectionMarker M,
@@ -317,17 +320,16 @@ void BlockInCriticalSectionChecker::handleUnlock(
317320
void BlockInCriticalSectionChecker::handleOpen(const CallEvent &Call,
318321
CheckerContext &C) const {
319322
const auto *Flag = Call.getArgExpr(1);
320-
static std::optional<int> ValueOfONonBlockVFlag =
321-
tryExpandAsInteger("O_NONBLOCK", C.getBugReporter().getPreprocessor());
322-
if (!ValueOfONonBlockVFlag)
323-
return;
324-
325323
SVal FlagSV = C.getState()->getSVal(Flag, C.getLocationContext());
326324
const llvm::APSInt *FlagV = FlagSV.getAsInteger();
327325
if (!FlagV)
328326
return;
329327

330-
if ((*FlagV & ValueOfONonBlockVFlag.value()) != 0)
328+
if (!O_NONBLOCKValue)
329+
O_NONBLOCKValue =
330+
tryExpandAsInteger("O_NONBLOCK", C.getBugReporter().getPreprocessor());
331+
332+
if (*O_NONBLOCKValue && ((*FlagV & **O_NONBLOCKValue) != 0))
331333
if (SymbolRef SR = Call.getReturnValue().getAsSymbol()) {
332334
C.addTransition(C.getState()->add<NonBlockFileDescriptor>(SR));
333335
}
@@ -348,18 +350,16 @@ void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call,
348350
// not cause block in these situations, don't report
349351
StringRef FuncName = Call.getCalleeIdentifier()->getName();
350352
if (FuncName == "read" || FuncName == "recv") {
351-
const auto *Arg = Call.getArgExpr(0);
352-
if (!Arg)
353+
SVal SV = Call.getArgSVal(0);
354+
SValBuilder &SVB = C.getSValBuilder();
355+
ProgramStateRef state = C.getState();
356+
ConditionTruthVal CTV =
357+
state->areEqual(SV, SVB.makeIntVal(-1, C.getASTContext().IntTy));
358+
if (CTV.isConstrainedTrue())
353359
return;
354360

355-
SVal SV = C.getSVal(Arg);
356-
if (const auto *IntValue = SV.getAsInteger()) {
357-
if (*IntValue == -1)
358-
return;
359-
}
360-
361-
SymbolRef SR = C.getSVal(Arg).getAsSymbol();
362-
if (SR && C.getState()->contains<NonBlockFileDescriptor>(SR)) {
361+
SymbolRef SR = SV.getAsSymbol();
362+
if (SR && state->contains<NonBlockFileDescriptor>(SR)) {
363363
return;
364364
}
365365
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// This is a fake system header with divide-by-zero bugs introduced in
2+
// c++ std library functions. We use these bugs to test hard-coded
3+
// suppression of diagnostics within standard library functions that are known
4+
// to produce false positives.
5+
6+
#pragma clang system_header
7+
namespace std {
8+
struct mutex {
9+
void lock() {}
10+
void unlock() {}
11+
};
12+
13+
template <typename T> struct lock_guard {
14+
lock_guard<T>(std::mutex) {}
15+
~lock_guard<T>() {}
16+
};
17+
} // namespace std

clang/test/Analysis/issue-124474.cpp

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,35 @@
66

77
// expected-no-diagnostics
88

9-
namespace std {
10-
struct mutex {
11-
void lock() {}
12-
void unlock() {}
13-
};
14-
template<typename T>
15-
struct lock_guard {
16-
lock_guard<T>(std::mutex) {}
17-
~lock_guard<T>() {}
18-
};
19-
template<typename T>
20-
struct unique_lock {
21-
unique_lock<T>(std::mutex) {}
22-
~unique_lock<T>() {}
23-
};
24-
template<typename T>
25-
struct not_real_lock {
26-
not_real_lock<T>(std::mutex) {}
27-
};
28-
} // namespace std
9+
#include "Inputs/system-header-simulator-cxx-std-locks.h"
2910

3011
std::mutex mtx;
3112
using ssize_t = long long;
3213
using size_t = unsigned long long;
33-
int open (const char *__file, int __oflag, ...);
14+
int open(const char *__file, int __oflag, ...);
3415
ssize_t read(int fd, void *buf, size_t count);
3516
void close(int fd);
36-
#define O_RDONLY 00
37-
# define O_NONBLOCK 04000
17+
#define O_RDONLY 00
18+
#define O_NONBLOCK 04000
3819

39-
void foo()
40-
{
41-
std::lock_guard<std::mutex> lock(mtx);
20+
void foo() {
21+
std::lock_guard<std::mutex> lock(mtx);
4222

43-
const char *filename = "example.txt";
44-
int fd = open(filename, O_RDONLY | O_NONBLOCK);
23+
const char *filename = "example.txt";
24+
int fd = open(filename, O_RDONLY | O_NONBLOCK);
4525

46-
char buffer[200] = {};
47-
read(fd, buffer, 199); // no-warning: fd is a non-block file descriptor
48-
close(fd);
26+
char buffer[200] = {};
27+
read(fd, buffer, 199); // no-warning: fd is a non-block file descriptor or equals to -1
28+
close(fd);
4929
}
5030

31+
void foo1(int fd) {
32+
std::lock_guard<std::mutex> lock(mtx);
33+
34+
const char *filename = "example.txt";
35+
char buffer[200] = {};
36+
if (fd == -1)
37+
read(fd, buffer, 199); // no-warning: consider file descriptor is a symbol equals to -1
38+
close(fd);
39+
}
40+

0 commit comments

Comments
 (0)