forked from OSchip/llvm-project
Added support to distinguish between both implicit and explicit null dereferences.
llvm-svn: 46846
This commit is contained in:
parent
3b5054dda0
commit
149512c013
|
@ -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<NodeTy*,5> ImplicitNullDerefTy;
|
||||
ImplicitNullDerefTy ImplicitNullDeref;
|
||||
typedef llvm::SmallPtrSet<NodeTy*,5> NullDerefTy;
|
||||
NullDerefTy ImplicitNullDeref;
|
||||
NullDerefTy ExplicitNullDeref;
|
||||
|
||||
|
||||
bool StateCleaned;
|
||||
|
@ -173,6 +174,11 @@ public:
|
|||
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
|
||||
/// nodes by processing the 'effects' of a block-level statement.
|
||||
void ProcessStmt(Stmt* S, StmtNodeBuilder& builder);
|
||||
|
@ -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);
|
||||
StateTy StNotNull = Assume(St, L1, true, isFeasibleNotNull);
|
||||
|
||||
if (isFeasible) {
|
||||
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<GRConstants::NodeTy*> :
|
|||
if (GraphPrintCheckerState->isImplicitNullDeref(N)) {
|
||||
Out << "\\|Implicit-Null Dereference.\\l";
|
||||
}
|
||||
else if (GraphPrintCheckerState->isExplicitNullDeref(N)) {
|
||||
Out << "\\|Explicit-Null Dereference.\\l";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue