From 149512c0131b6c85915f6c62b21372705e94ecc2 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 7 Feb 2008 06:04:18 +0000 Subject: [PATCH] Added support to distinguish between both implicit and explicit null dereferences. llvm-svn: 46846 --- clang/Analysis/GRConstants.cpp | 59 ++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/clang/Analysis/GRConstants.cpp b/clang/Analysis/GRConstants.cpp index 44c5d5166468..9fc828616af5 100644 --- a/clang/Analysis/GRConstants.cpp +++ b/clang/Analysis/GRConstants.cpp @@ -126,8 +126,9 @@ protected: /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from /// taking a dereference on a symbolic pointer that may be NULL. - typedef llvm::SmallPtrSet ImplicitNullDerefTy; - ImplicitNullDerefTy ImplicitNullDeref; + typedef llvm::SmallPtrSet NullDerefTy; + NullDerefTy ImplicitNullDeref; + NullDerefTy ExplicitNullDeref; bool StateCleaned; @@ -172,6 +173,11 @@ public: bool isImplicitNullDeref(const NodeTy* N) const { return N->isSink() && ImplicitNullDeref.count(const_cast(N)) != 0; } + + bool isExplicitNullDeref(const NodeTy* N) const { + return N->isSink() && ExplicitNullDeref.count(const_cast(N)) != 0; + } + /// ProcessStmt - Called by GREngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. @@ -249,7 +255,8 @@ public: StateTy AssumeSymInt(StateTy St, bool Assumption, const SymIntConstraint& C, bool& isFeasible); - NodeTy* Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St); + NodeTy* Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St, + bool AlwaysMakeNode = false); /// Nodify - This version of Nodify is used to batch process a set of states. /// The states are not guaranteed to be unique. @@ -570,10 +577,11 @@ GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) { } GRConstants::NodeTy* -GRConstants::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St) { +GRConstants::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St, + bool AlwaysMakeNode) { // If the state hasn't changed, don't generate a new node. - if (St == Pred->getState()) + if (!AlwaysMakeNode && St == Pred->getState()) return NULL; NodeTy* N = Builder->generateNode(S, St, Pred); @@ -777,28 +785,34 @@ void GRConstants::VisitUnaryOperator(UnaryOperator* U, // // We add these assumptions. - bool isFeasible; - - // "Assume" that the pointer is NULL. - StateTy StNull = Assume(St, L1, false, isFeasible); - - if (isFeasible) { - NodeTy* NullNode = Nodify(Dst, U, N1, StNull); - if (NullNode) { - NullNode->markAsSink(); - ImplicitNullDeref.insert(NullNode); - } - } - + bool isFeasibleNotNull; + // "Assume" that the pointer is Not-NULL. - StateTy StNotNull = Assume(St, L1, true, isFeasible); - - if (isFeasible) { + StateTy StNotNull = Assume(St, L1, true, isFeasibleNotNull); + + if (isFeasibleNotNull) { QualType T = U->getType(); Nodify(Dst, U, N1, SetValue(StNotNull, U, GetValue(StNotNull, L1, &T))); } + bool isFeasibleNull; + + // "Assume" that the pointer is NULL. + StateTy StNull = Assume(St, L1, false, isFeasibleNull); + + if (isFeasibleNull) { + NodeTy* NullNode = Nodify(Dst, U, N1, StNull, true); + if (NullNode) { + NullNode->markAsSink(); + + if (isFeasibleNotNull) + ImplicitNullDeref.insert(NullNode); + else + ExplicitNullDeref.insert(NullNode); + } + } + break; } @@ -1254,6 +1268,9 @@ struct VISIBILITY_HIDDEN DOTGraphTraits : if (GraphPrintCheckerState->isImplicitNullDeref(N)) { Out << "\\|Implicit-Null Dereference.\\l"; } + else if (GraphPrintCheckerState->isExplicitNullDeref(N)) { + Out << "\\|Explicit-Null Dereference.\\l"; + } break; }