From 212182d12b648f41041650a8dbe3476400245204 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 8 Apr 2010 22:15:34 +0000 Subject: [PATCH] For 'open' check in UnixAPIChecker, hard code value of 'O_CREAT' on Darwin. This is still not an ideal solution, but should disable the check for other targets where the value of O_CREAT is different. llvm-svn: 100818 --- .../include/clang/Analysis/Support/Optional.h | 2 + clang/lib/Checker/UnixAPIChecker.cpp | 52 ++++++++++++------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Analysis/Support/Optional.h b/clang/include/clang/Analysis/Support/Optional.h index a4e6d519a04f..77c4825b4e53 100644 --- a/clang/include/clang/Analysis/Support/Optional.h +++ b/clang/include/clang/Analysis/Support/Optional.h @@ -16,6 +16,8 @@ #ifndef LLVM_CLANG_ANALYSIS_OPTIONAL #define LLVM_CLANG_ANALYSIS_OPTIONAL +#include + namespace clang { template diff --git a/clang/lib/Checker/UnixAPIChecker.cpp b/clang/lib/Checker/UnixAPIChecker.cpp index 213e79800537..31864e74550d 100644 --- a/clang/lib/Checker/UnixAPIChecker.cpp +++ b/clang/lib/Checker/UnixAPIChecker.cpp @@ -13,15 +13,13 @@ //===----------------------------------------------------------------------===// #include "GRExprEngineInternalChecks.h" -#include "clang/Checker/PathSensitive/CheckerVisitor.h" -#include "clang/Checker/BugReporter/BugType.h" #include "clang/Analysis/Support/Optional.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Checker/BugReporter/BugType.h" +#include "clang/Checker/PathSensitive/CheckerVisitor.h" #include "llvm/ADT/StringSwitch.h" #include -#include "clang/Basic/TargetInfo.h" - - using namespace clang; namespace { @@ -34,6 +32,9 @@ class UnixAPIChecker : public CheckerVisitor { BugType *BTypes[NumChecks]; +public: + Optional Val_O_CREAT; + public: UnixAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); } static void *getTag() { static unsigned tag = 0; return &tag; } @@ -60,10 +61,21 @@ static inline void LazyInitialize(BugType *&BT, const char *name) { // "open" (man 2 open) //===----------------------------------------------------------------------===// -static void CheckOpen(CheckerContext &C, const CallExpr *CE, BugType *&BT) { - if (C.getASTContext().Target.getTriple().getVendor() != llvm::Triple::Apple) - return; - +static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC, + const CallExpr *CE, BugType *&BT) { + // The definition of O_CREAT is platform specific. We need a better way + // of querying this information from the checking environment. + if (!UC.Val_O_CREAT.hasValue()) { + if (C.getASTContext().Target.getTriple().getVendor() == llvm::Triple::Apple) + UC.Val_O_CREAT = 0x0200; + else { + // FIXME: We need a more general way of getting the O_CREAT value. + // We could possibly grovel through the preprocessor state, but + // that would require passing the Preprocessor object to the GRExprEngine. + return; + } + } + LazyInitialize(BT, "Improper use of 'open'"); // Look at the 'oflags' argument for the O_CREAT flag. @@ -85,7 +97,7 @@ static void CheckOpen(CheckerContext &C, const CallExpr *CE, BugType *&BT) { } NonLoc oflags = cast(V); NonLoc ocreateFlag = - cast(C.getValueManager().makeIntVal((uint64_t) O_CREAT, + cast(C.getValueManager().makeIntVal(UC.Val_O_CREAT.getValue(), oflagsEx->getType())); SVal maskedFlagsUC = C.getSValuator().EvalBinOpNN(state, BinaryOperator::And, oflags, ocreateFlag, @@ -121,8 +133,8 @@ static void CheckOpen(CheckerContext &C, const CallExpr *CE, BugType *&BT) { // pthread_once //===----------------------------------------------------------------------===// -static void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE, - BugType *&BT) { +static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &, + const CallExpr *CE, BugType *&BT) { // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker. // They can possibly be refactored. @@ -164,18 +176,21 @@ static void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE, // Central dispatch function. //===----------------------------------------------------------------------===// -typedef void (*SubChecker)(CheckerContext &C, const CallExpr *CE, BugType *&BT); +typedef void (*SubChecker)(CheckerContext &C, UnixAPIChecker &UC, + const CallExpr *CE, BugType *&BT); namespace { class SubCheck { SubChecker SC; + UnixAPIChecker *UC; BugType **BT; public: - SubCheck(SubChecker sc, BugType *& bt) : SC(sc), BT(&bt) {} - SubCheck() : SC(NULL), BT(NULL) {} + SubCheck(SubChecker sc, UnixAPIChecker *uc, BugType *& bt) : SC(sc), UC(uc), + BT(&bt) {} + SubCheck() : SC(NULL), UC(NULL), BT(NULL) {} void run(CheckerContext &C, const CallExpr *CE) const { if (SC) - SC(C, CE, *BT); + SC(C, *UC, CE, *BT); } }; } // end anonymous namespace @@ -197,8 +212,9 @@ void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { const SubCheck &SC = llvm::StringSwitch(FI->getName()) - .Case("open", SubCheck(CheckOpen, BTypes[OpenFn])) - .Case("pthread_once", SubCheck(CheckPthreadOnce, BTypes[PthreadOnceFn])) + .Case("open", SubCheck(CheckOpen, this, BTypes[OpenFn])) + .Case("pthread_once", SubCheck(CheckPthreadOnce, this, + BTypes[PthreadOnceFn])) .Default(SubCheck()); SC.run(C, CE);