Added support to distinguish between both implicit and explicit null dereferences.

llvm-svn: 46846
This commit is contained in:
Ted Kremenek 2008-02-07 06:04:18 +00:00
parent 3b5054dda0
commit 149512c013
1 changed files with 38 additions and 21 deletions

View File

@ -126,8 +126,9 @@ protected:
/// ImplicitNullDeref - Nodes in the ExplodedGraph that result from /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on a symbolic pointer that may be NULL. /// taking a dereference on a symbolic pointer that may be NULL.
typedef llvm::SmallPtrSet<NodeTy*,5> ImplicitNullDerefTy; typedef llvm::SmallPtrSet<NodeTy*,5> NullDerefTy;
ImplicitNullDerefTy ImplicitNullDeref; NullDerefTy ImplicitNullDeref;
NullDerefTy ExplicitNullDeref;
bool StateCleaned; bool StateCleaned;
@ -173,6 +174,11 @@ public:
return N->isSink() && ImplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0; return N->isSink() && ImplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
} }
bool isExplicitNullDeref(const NodeTy* N) const {
return N->isSink() && ExplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
}
/// ProcessStmt - Called by GREngine. Used to generate new successor /// ProcessStmt - Called by GREngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement. /// nodes by processing the 'effects' of a block-level statement.
void ProcessStmt(Stmt* S, StmtNodeBuilder& builder); void ProcessStmt(Stmt* S, StmtNodeBuilder& builder);
@ -249,7 +255,8 @@ public:
StateTy AssumeSymInt(StateTy St, bool Assumption, const SymIntConstraint& C, StateTy AssumeSymInt(StateTy St, bool Assumption, const SymIntConstraint& C,
bool& isFeasible); 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. /// Nodify - This version of Nodify is used to batch process a set of states.
/// The states are not guaranteed to be unique. /// The states are not guaranteed to be unique.
@ -570,10 +577,11 @@ GRConstants::StateTy GRConstants::RemoveDeadBindings(Stmt* Loc, StateTy M) {
} }
GRConstants::NodeTy* 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 the state hasn't changed, don't generate a new node.
if (St == Pred->getState()) if (!AlwaysMakeNode && St == Pred->getState())
return NULL; return NULL;
NodeTy* N = Builder->generateNode(S, St, Pred); NodeTy* N = Builder->generateNode(S, St, Pred);
@ -777,28 +785,34 @@ void GRConstants::VisitUnaryOperator(UnaryOperator* U,
// //
// We add these assumptions. // We add these assumptions.
bool isFeasible; bool isFeasibleNotNull;
// "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);
}
}
// "Assume" that the pointer is Not-NULL. // "Assume" that the pointer is Not-NULL.
StateTy StNotNull = Assume(St, L1, true, isFeasible); StateTy StNotNull = Assume(St, L1, true, isFeasibleNotNull);
if (isFeasible) { if (isFeasibleNotNull) {
QualType T = U->getType(); QualType T = U->getType();
Nodify(Dst, U, N1, SetValue(StNotNull, U, Nodify(Dst, U, N1, SetValue(StNotNull, U,
GetValue(StNotNull, L1, &T))); 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; break;
} }
@ -1254,6 +1268,9 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRConstants::NodeTy*> :
if (GraphPrintCheckerState->isImplicitNullDeref(N)) { if (GraphPrintCheckerState->isImplicitNullDeref(N)) {
Out << "\\|Implicit-Null Dereference.\\l"; Out << "\\|Implicit-Null Dereference.\\l";
} }
else if (GraphPrintCheckerState->isExplicitNullDeref(N)) {
Out << "\\|Explicit-Null Dereference.\\l";
}
break; break;
} }