Skip to content

Commit 37c19f9

Browse files
[analyzer] UnixAPIMisuseChecker Get O_CREAT from preprocessor (llvm#81855)
Now calling `open` with the `O_CREAT` flag and no mode parameter will raise an issue in any system that defines `O_CREAT`. The value for this flag is obtained after the full source code has been parsed, leveraging `checkASTDecl`. Hence, any `#define` or `#undefine` of `O_CREAT` following an `open` may alter the results. Nevertheless, since redefining reserved identifiers is UB, this is probably ok.
1 parent c7799fa commit 37c19f9

File tree

4 files changed

+404
-357
lines changed

4 files changed

+404
-357
lines changed

clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/StaticAnalyzer/Core/Checker.h"
1919
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
2020
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21+
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
2122
#include "llvm/ADT/STLExtras.h"
2223
#include "llvm/ADT/SmallString.h"
2324
#include "llvm/ADT/StringExtras.h"
@@ -39,13 +40,18 @@ enum class OpenVariant {
3940

4041
namespace {
4142

42-
class UnixAPIMisuseChecker : public Checker< check::PreStmt<CallExpr> > {
43+
class UnixAPIMisuseChecker
44+
: public Checker<check::PreStmt<CallExpr>,
45+
check::ASTDecl<TranslationUnitDecl>> {
4346
const BugType BT_open{this, "Improper use of 'open'", categories::UnixAPI};
4447
const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'",
4548
categories::UnixAPI};
4649
mutable std::optional<uint64_t> Val_O_CREAT;
4750

4851
public:
52+
void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr,
53+
BugReporter &BR) const;
54+
4955
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
5056

5157
void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
@@ -55,11 +61,8 @@ class UnixAPIMisuseChecker : public Checker< check::PreStmt<CallExpr> > {
5561
void CheckOpenVariant(CheckerContext &C,
5662
const CallExpr *CE, OpenVariant Variant) const;
5763

58-
void ReportOpenBug(CheckerContext &C,
59-
ProgramStateRef State,
60-
const char *Msg,
64+
void ReportOpenBug(CheckerContext &C, ProgramStateRef State, const char *Msg,
6165
SourceRange SR) const;
62-
6366
};
6467

6568
class UnixAPIPortabilityChecker : public Checker< check::PreStmt<CallExpr> > {
@@ -90,7 +93,21 @@ class UnixAPIPortabilityChecker : public Checker< check::PreStmt<CallExpr> > {
9093
const char *fn) const;
9194
};
9295

93-
} //end anonymous namespace
96+
} // end anonymous namespace
97+
98+
void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU,
99+
AnalysisManager &Mgr,
100+
BugReporter &) const {
101+
// The definition of O_CREAT is platform specific.
102+
// Try to get the macro value from the preprocessor.
103+
Val_O_CREAT = tryExpandAsInteger("O_CREAT", Mgr.getPreprocessor());
104+
// If we failed, fall-back to known values.
105+
if (!Val_O_CREAT) {
106+
if (TU->getASTContext().getTargetInfo().getTriple().getVendor() ==
107+
llvm::Triple::Apple)
108+
Val_O_CREAT = 0x0200;
109+
}
110+
}
94111

95112
//===----------------------------------------------------------------------===//
96113
// "open" (man 2 open)
@@ -204,19 +221,8 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
204221
return;
205222
}
206223

207-
// The definition of O_CREAT is platform specific. We need a better way
208-
// of querying this information from the checking environment.
209224
if (!Val_O_CREAT) {
210-
if (C.getASTContext().getTargetInfo().getTriple().getVendor()
211-
== llvm::Triple::Apple)
212-
Val_O_CREAT = 0x0200;
213-
else {
214-
// FIXME: We need a more general way of getting the O_CREAT value.
215-
// We could possibly grovel through the preprocessor state, but
216-
// that would require passing the Preprocessor object to the ExprEngine.
217-
// See also: MallocChecker.cpp / M_ZERO.
218-
return;
219-
}
225+
return;
220226
}
221227

222228
// Now check if oflags has O_CREAT set.

0 commit comments

Comments
 (0)