summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Checker/UnixAPIChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Checker/UnixAPIChecker.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Checker/UnixAPIChecker.cpp222
1 files changed, 0 insertions, 222 deletions
diff --git a/contrib/llvm/tools/clang/lib/Checker/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/Checker/UnixAPIChecker.cpp
deleted file mode 100644
index de7346d..0000000
--- a/contrib/llvm/tools/clang/lib/Checker/UnixAPIChecker.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-//= UnixAPIChecker.h - Checks preconditions for various Unix APIs --*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This defines UnixAPIChecker, which is an assortment of checks on calls
-// to various, widely used UNIX/Posix functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "GRExprEngineInternalChecks.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Checker/BugReporter/BugType.h"
-#include "clang/Checker/PathSensitive/CheckerVisitor.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringSwitch.h"
-#include <fcntl.h>
-
-using namespace clang;
-using llvm::Optional;
-
-namespace {
-class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> {
- enum SubChecks {
- OpenFn = 0,
- PthreadOnceFn = 1,
- NumChecks
- };
-
- BugType *BTypes[NumChecks];
-
-public:
- Optional<uint64_t> Val_O_CREAT;
-
-public:
- UnixAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); }
- static void *getTag() { static unsigned tag = 0; return &tag; }
-
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-} //end anonymous namespace
-
-void clang::RegisterUnixAPIChecker(GRExprEngine &Eng) {
- Eng.registerCheck(new UnixAPIChecker());
-}
-
-//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static inline void LazyInitialize(BugType *&BT, const char *name) {
- if (BT)
- return;
- BT = new BugType(name, "Unix API");
-}
-
-//===----------------------------------------------------------------------===//
-// "open" (man 2 open)
-//===----------------------------------------------------------------------===//
-
-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.
- const GRState *state = C.getState();
-
- if (CE->getNumArgs() < 2) {
- // The frontend should issue a warning for this case, so this is a sanity
- // check.
- return;
- }
-
- // Now check if oflags has O_CREAT set.
- const Expr *oflagsEx = CE->getArg(1);
- const SVal V = state->getSVal(oflagsEx);
- if (!isa<NonLoc>(V)) {
- // The case where 'V' can be a location can only be due to a bad header,
- // so in this case bail out.
- return;
- }
- NonLoc oflags = cast<NonLoc>(V);
- NonLoc ocreateFlag =
- cast<NonLoc>(C.getValueManager().makeIntVal(UC.Val_O_CREAT.getValue(),
- oflagsEx->getType()));
- SVal maskedFlagsUC = C.getSValuator().EvalBinOpNN(state, BO_And,
- oflags, ocreateFlag,
- oflagsEx->getType());
- if (maskedFlagsUC.isUnknownOrUndef())
- return;
- DefinedSVal maskedFlags = cast<DefinedSVal>(maskedFlagsUC);
-
- // Check if maskedFlags is non-zero.
- const GRState *trueState, *falseState;
- llvm::tie(trueState, falseState) = state->Assume(maskedFlags);
-
- // Only emit an error if the value of 'maskedFlags' is properly
- // constrained;
- if (!(trueState && !falseState))
- return;
-
- if (CE->getNumArgs() < 3) {
- ExplodedNode *N = C.GenerateSink(trueState);
- if (!N)
- return;
-
- EnhancedBugReport *report =
- new EnhancedBugReport(*BT,
- "Call to 'open' requires a third argument when "
- "the 'O_CREAT' flag is set", N);
- report->addRange(oflagsEx->getSourceRange());
- C.EmitReport(report);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// pthread_once
-//===----------------------------------------------------------------------===//
-
-static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &,
- const CallExpr *CE, BugType *&BT) {
-
- // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
- // They can possibly be refactored.
-
- LazyInitialize(BT, "Improper use of 'pthread_once'");
-
- if (CE->getNumArgs() < 1)
- return;
-
- // Check if the first argument is stack allocated. If so, issue a warning
- // because that's likely to be bad news.
- const GRState *state = C.getState();
- const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
- if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
- return;
-
- ExplodedNode *N = C.GenerateSink(state);
- if (!N)
- return;
-
- llvm::SmallString<256> S;
- llvm::raw_svector_ostream os(S);
- os << "Call to 'pthread_once' uses";
- if (const VarRegion *VR = dyn_cast<VarRegion>(R))
- os << " the local variable '" << VR->getDecl()->getName() << '\'';
- else
- os << " stack allocated memory";
- os << " for the \"control\" value. Using such transient memory for "
- "the control value is potentially dangerous.";
- if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
- os << " Perhaps you intended to declare the variable as 'static'?";
-
- EnhancedBugReport *report = new EnhancedBugReport(*BT, os.str(), N);
- report->addRange(CE->getArg(0)->getSourceRange());
- C.EmitReport(report);
-}
-
-//===----------------------------------------------------------------------===//
-// Central dispatch function.
-//===----------------------------------------------------------------------===//
-
-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, 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, *UC, CE, *BT);
- }
- };
-} // end anonymous namespace
-
-void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
- // Get the callee. All the functions we care about are C functions
- // with simple identifiers.
- const GRState *state = C.getState();
- const Expr *Callee = CE->getCallee();
- const FunctionTextRegion *Fn =
- dyn_cast_or_null<FunctionTextRegion>(state->getSVal(Callee).getAsRegion());
-
- if (!Fn)
- return;
-
- const IdentifierInfo *FI = Fn->getDecl()->getIdentifier();
- if (!FI)
- return;
-
- const SubCheck &SC =
- llvm::StringSwitch<SubCheck>(FI->getName())
- .Case("open", SubCheck(CheckOpen, this, BTypes[OpenFn]))
- .Case("pthread_once", SubCheck(CheckPthreadOnce, this,
- BTypes[PthreadOnceFn]))
- .Default(SubCheck());
-
- SC.run(C, CE);
-}
OpenPOWER on IntegriCloud