From: Ted Kremenek Date: Thu, 7 Feb 2008 06:04:18 +0000 (+0000) Subject: Added support to distinguish between both implicit and explicit null dereferences. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=63a4f697a3c6cf4a8b7911830830d2738da7217a;p=clang Added support to distinguish between both implicit and explicit null dereferences. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46846 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp index 44c5d51664..9fc828616a 100644 --- a/Analysis/GRConstants.cpp +++ b/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; + bool isFeasibleNotNull; + + // "Assume" that the pointer is Not-NULL. + 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, isFeasible); + StateTy StNull = Assume(St, L1, false, isFeasibleNull); - if (isFeasible) { - NodeTy* NullNode = Nodify(Dst, U, N1, StNull); + if (isFeasibleNull) { + NodeTy* NullNode = Nodify(Dst, U, N1, StNull, true); if (NullNode) { NullNode->markAsSink(); - ImplicitNullDeref.insert(NullNode); + + if (isFeasibleNotNull) + ImplicitNullDeref.insert(NullNode); + else + ExplicitNullDeref.insert(NullNode); } } - // "Assume" that the pointer is Not-NULL. - StateTy StNotNull = Assume(St, L1, true, isFeasible); - - if (isFeasible) { - QualType T = U->getType(); - Nodify(Dst, U, N1, SetValue(StNotNull, U, - GetValue(StNotNull, L1, &T))); - } - 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; }