@@ -40,17 +40,28 @@ enum class OpenVariant {
40
40
OpenAt
41
41
};
42
42
43
+ static std::optional<int > getCreateFlagValue (const ASTContext &Ctx,
44
+ const Preprocessor &PP) {
45
+ std::optional<int > MacroVal = tryExpandAsInteger (" O_CREAT" , PP);
46
+ if (MacroVal.has_value ())
47
+ return MacroVal;
48
+
49
+ // If we failed, fall-back to known values.
50
+ if (Ctx.getTargetInfo ().getTriple ().getVendor () == llvm::Triple::Apple)
51
+ return {0x0200 };
52
+ return MacroVal;
53
+ }
54
+
43
55
namespace {
44
56
45
- class UnixAPIMisuseChecker
46
- : public Checker<check::PreCall, check::ASTDecl<TranslationUnitDecl>> {
57
+ class UnixAPIMisuseChecker : public Checker <check::PreCall> {
47
58
const BugType BT_open{this , " Improper use of 'open'" , categories::UnixAPI};
48
59
const BugType BT_getline{this , " Improper use of getdelim" ,
49
60
categories::UnixAPI};
50
61
const BugType BT_pthreadOnce{this , " Improper use of 'pthread_once'" ,
51
62
categories::UnixAPI};
52
63
const BugType BT_ArgumentNull{this , " NULL pointer" , categories::UnixAPI};
53
- mutable std::optional<uint64_t > Val_O_CREAT;
64
+ const std::optional<int > Val_O_CREAT;
54
65
55
66
ProgramStateRef
56
67
EnsurePtrNotNull (SVal PtrVal, const Expr *PtrExpr, CheckerContext &C,
@@ -63,6 +74,9 @@ class UnixAPIMisuseChecker
63
74
const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const ;
64
75
65
76
public:
77
+ UnixAPIMisuseChecker (const ASTContext &Ctx, const Preprocessor &PP)
78
+ : Val_O_CREAT(getCreateFlagValue(Ctx, PP)) {}
79
+
66
80
void checkASTDecl (const TranslationUnitDecl *TU, AnalysisManager &Mgr,
67
81
BugReporter &BR) const ;
68
82
@@ -134,20 +148,6 @@ ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull(
134
148
return PtrNotNull;
135
149
}
136
150
137
- void UnixAPIMisuseChecker::checkASTDecl (const TranslationUnitDecl *TU,
138
- AnalysisManager &Mgr,
139
- BugReporter &) const {
140
- // The definition of O_CREAT is platform specific.
141
- // Try to get the macro value from the preprocessor.
142
- Val_O_CREAT = tryExpandAsInteger (" O_CREAT" , Mgr.getPreprocessor ());
143
- // If we failed, fall-back to known values.
144
- if (!Val_O_CREAT) {
145
- if (TU->getASTContext ().getTargetInfo ().getTriple ().getVendor () ==
146
- llvm::Triple::Apple)
147
- Val_O_CREAT = 0x0200 ;
148
- }
149
- }
150
-
151
151
// ===----------------------------------------------------------------------===//
152
152
// "open" (man 2 open)
153
153
// ===----------------------------------------------------------------------===/
@@ -262,7 +262,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
262
262
return ;
263
263
}
264
264
265
- if (!Val_O_CREAT) {
265
+ if (!Val_O_CREAT. has_value () ) {
266
266
return ;
267
267
}
268
268
@@ -276,7 +276,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
276
276
}
277
277
NonLoc oflags = V.castAs <NonLoc>();
278
278
NonLoc ocreateFlag = C.getSValBuilder ()
279
- .makeIntVal (* Val_O_CREAT, oflagsEx->getType ())
279
+ .makeIntVal (Val_O_CREAT. value () , oflagsEx->getType ())
280
280
.castAs <NonLoc>();
281
281
SVal maskedFlagsUC = C.getSValBuilder ().evalBinOpNN (state, BO_And,
282
282
oflags, ocreateFlag,
@@ -621,14 +621,17 @@ void UnixAPIPortabilityChecker::checkPreStmt(const CallExpr *CE,
621
621
// Registration.
622
622
// ===----------------------------------------------------------------------===//
623
623
624
- #define REGISTER_CHECKER (CHECKERNAME ) \
625
- void ento::register ##CHECKERNAME(CheckerManager &mgr) { \
626
- mgr.registerChecker <CHECKERNAME>(); \
627
- } \
628
- \
629
- bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) { \
630
- return true ; \
631
- }
624
+ void ento::registerUnixAPIMisuseChecker (CheckerManager &Mgr) {
625
+ Mgr.registerChecker <UnixAPIMisuseChecker>(Mgr.getASTContext (),
626
+ Mgr.getPreprocessor ());
627
+ }
628
+ bool ento::shouldRegisterUnixAPIMisuseChecker (const CheckerManager &Mgr) {
629
+ return true ;
630
+ }
632
631
633
- REGISTER_CHECKER (UnixAPIMisuseChecker)
634
- REGISTER_CHECKER(UnixAPIPortabilityChecker)
632
+ void ento::registerUnixAPIPortabilityChecker (CheckerManager &Mgr) {
633
+ Mgr.registerChecker <UnixAPIPortabilityChecker>();
634
+ }
635
+ bool ento::shouldRegisterUnixAPIPortabilityChecker (const CheckerManager &Mgr) {
636
+ return true ;
637
+ }
0 commit comments