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
|
/// 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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue