diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-11-18 14:59:57 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-11-18 14:59:57 +0000 |
commit | 741c13ecc20fb35b836ad690aeecd402f002d654 (patch) | |
tree | 60a1694bec5a44d15456acc880cb2f91619f66aa /lib/Analysis/DereferenceChecker.cpp | |
parent | b3a51061b1b9c4add078237850649f7c9efb13ab (diff) | |
download | FreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.zip FreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.tar.gz |
Update clang to r89205.
Diffstat (limited to 'lib/Analysis/DereferenceChecker.cpp')
-rw-r--r-- | lib/Analysis/DereferenceChecker.cpp | 161 |
1 files changed, 82 insertions, 79 deletions
diff --git a/lib/Analysis/DereferenceChecker.cpp b/lib/Analysis/DereferenceChecker.cpp index 33c85d5..c3aa8f3 100644 --- a/lib/Analysis/DereferenceChecker.cpp +++ b/lib/Analysis/DereferenceChecker.cpp @@ -13,100 +13,103 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h" +#include "clang/Analysis/PathSensitive/Checker.h" #include "clang/Analysis/PathSensitive/GRExprEngine.h" #include "clang/Analysis/PathSensitive/BugReporter.h" +#include "GRExprEngineInternalChecks.h" using namespace clang; -void *NullDerefChecker::getTag() { - static int x = 0; - return &x; -} - -ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V, - GRExprEngine &Eng) { - Loc *LV = dyn_cast<Loc>(&V); - - // If the value is not a location, don't touch the node. - if (!LV) - return Pred; - - const GRState *NotNullState = state->Assume(*LV, true); - const GRState *NullState = state->Assume(*LV, false); +namespace { +class VISIBILITY_HIDDEN DereferenceChecker : public Checker { + BuiltinBug *BT_null; + BuiltinBug *BT_undef; + llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes; +public: + DereferenceChecker() : BT_null(0), BT_undef(0) {} + static void *getTag() { static int tag = 0; return &tag; } + void VisitLocation(CheckerContext &C, const Stmt *S, SVal location); - GRStmtNodeBuilder &Builder = Eng.getBuilder(); - BugReporter &BR = Eng.getBugReporter(); - - // The explicit NULL case. - if (NullState) { - // Use the GDM to mark in the state what lval was null. - const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV); - NullState = NullState->set<GRState::NullDerefTag>(PersistentLV); - - ExplodedNode *N = Builder.generateNode(S, NullState, Pred, - ProgramPoint::PostNullCheckFailedKind); - if (N) { - N->markAsSink(); - - if (!NotNullState) { // Explicit null case. - if (!BT) - BT = new BuiltinBug(NULL, "Null dereference", - "Dereference of null pointer"); - - EnhancedBugReport *R = - new EnhancedBugReport(*BT, BT->getDescription().c_str(), N); - - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - bugreporter::GetDerefExpr(N)); - - BR.EmitReport(R); - - return 0; - } else // Implicit null case. - ImplicitNullDerefNodes.push_back(N); - } + std::pair<ExplodedNode * const*, ExplodedNode * const*> + getImplicitNodes() const { + return std::make_pair(ImplicitNullDerefNodes.data(), + ImplicitNullDerefNodes.data() + + ImplicitNullDerefNodes.size()); } - - if (!NotNullState) - return 0; +}; +} // end anonymous namespace - return Builder.generateNode(S, NotNullState, Pred, - ProgramPoint::PostLocationChecksSucceedKind); +void clang::RegisterDereferenceChecker(GRExprEngine &Eng) { + Eng.registerCheck(new DereferenceChecker()); } - -void *UndefDerefChecker::getTag() { - static int x = 0; - return &x; +std::pair<ExplodedNode * const *, ExplodedNode * const *> +clang::GetImplicitNullDereferences(GRExprEngine &Eng) { + DereferenceChecker *checker = Eng.getChecker<DereferenceChecker>(); + if (!checker) + return std::make_pair((ExplodedNode * const *) 0, + (ExplodedNode * const *) 0); + return checker->getImplicitNodes(); } -ExplodedNode *UndefDerefChecker::CheckLocation(const Stmt *S, - ExplodedNode *Pred, - const GRState *state, SVal V, - GRExprEngine &Eng) { - GRStmtNodeBuilder &Builder = Eng.getBuilder(); - BugReporter &BR = Eng.getBugReporter(); - - if (V.isUndef()) { - ExplodedNode *N = Builder.generateNode(S, state, Pred, - ProgramPoint::PostUndefLocationCheckFailedKind); +void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, + SVal l) { + // Check for dereference of an undefined value. + if (l.isUndef()) { + ExplodedNode *N = C.GenerateNode(S, true); if (N) { - N->markAsSink(); + if (!BT_undef) + BT_undef = new BuiltinBug("Dereference of undefined pointer value"); + + EnhancedBugReport *report = + new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N); + report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, + bugreporter::GetDerefExpr(N)); + C.EmitReport(report); + } + return; + } + + DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l); + + // Check for null dereferences. + if (!isa<Loc>(location)) + return; + + const GRState *state = C.getState(); + const GRState *notNullState, *nullState; + llvm::tie(notNullState, nullState) = state->Assume(location); + + // The explicit NULL case. + if (nullState) { + // Generate an error node. + ExplodedNode *N = C.GenerateNode(S, nullState, true); + if (N) { + if (!notNullState) { + // We know that 'location' cannot be non-null. This is what + // we call an "explicit" null dereference. + if (!BT_null) + BT_null = new BuiltinBug("Null pointer dereference", + "Dereference of null pointer"); - if (!BT) - BT = new BuiltinBug(0, "Undefined dereference", - "Dereference of undefined pointer value"); + EnhancedBugReport *report = + new EnhancedBugReport(*BT_null, BT_null->getDescription(), N); + report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, + bugreporter::GetDerefExpr(N)); + + C.EmitReport(report); + return; + } - EnhancedBugReport *R = - new EnhancedBugReport(*BT, BT->getDescription().c_str(), N); - R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - bugreporter::GetDerefExpr(N)); - BR.EmitReport(R); + // Otherwise, we have the case where the location could either be + // null or not-null. Record the error node as an "implicit" null + // dereference. + ImplicitNullDerefNodes.push_back(N); } - return 0; } - - return Pred; + + // From this point forward, we know that the location is not null. + assert(notNullState); + C.addTransition(state != nullState ? C.GenerateNode(S, notNullState) : + C.getPredecessor()); } - |