forked from OSchip/llvm-project
Added extra check for calls to functions where we pass undefined values
as arguments. llvm-svn: 47778
This commit is contained in:
parent
e8ddaba169
commit
51e87ea210
|
@ -481,12 +481,27 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred,
|
|||
NodeSet DstTmp;
|
||||
|
||||
Visit(*AI, Pred, DstTmp);
|
||||
|
||||
if (DstTmp.empty()) DstTmp.Add(Pred);
|
||||
|
||||
Expr* CurrentArg = *AI;
|
||||
++AI;
|
||||
|
||||
for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI != DE; ++DI)
|
||||
for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI != DE; ++DI) {
|
||||
if (GetRVal((*DI)->getState(), CurrentArg).isUndef()) {
|
||||
|
||||
NodeTy* N = Builder->generateNode(CE, (*DI)->getState(), *DI);
|
||||
|
||||
if (N) {
|
||||
N->markAsSink();
|
||||
UndefArgs.insert(N);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
VisitCall(CE, *DI, AI, AE, Dst);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -509,8 +524,10 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred,
|
|||
|
||||
if (L.isUndef() || isa<lval::ConcreteInt>(L)) {
|
||||
NodeTy* N = Builder->generateNode(CE, St, *DI);
|
||||
N->markAsSink();
|
||||
BadCalls.insert(N);
|
||||
if (N) {
|
||||
N->markAsSink();
|
||||
BadCalls.insert(N);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1591,7 +1608,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
|||
GraphPrintCheckerState->isUndefControlFlow(N) ||
|
||||
GraphPrintCheckerState->isBadDivide(N) ||
|
||||
GraphPrintCheckerState->isUndefResult(N) ||
|
||||
GraphPrintCheckerState->isBadCall(N))
|
||||
GraphPrintCheckerState->isBadCall(N) ||
|
||||
GraphPrintCheckerState->isUndefArg(N))
|
||||
return "color=\"red\",style=\"filled\"";
|
||||
|
||||
if (GraphPrintCheckerState->isNoReturnCall(N))
|
||||
|
@ -1639,6 +1657,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
|||
Out << "\\|Call to function marked \"noreturn\".";
|
||||
else if (GraphPrintCheckerState->isBadCall(N))
|
||||
Out << "\\|Call to NULL/Undefined.";
|
||||
else if (GraphPrintCheckerState->isUndefArg(N))
|
||||
Out << "\\|Argument in call is undefined";
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -106,6 +106,11 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
|
|||
CheckerState->bad_calls_begin(),
|
||||
CheckerState->bad_calls_end(),
|
||||
"Call using a NULL or undefined function pointer value.");
|
||||
|
||||
EmitWarning(Diag, SrcMgr,
|
||||
CheckerState->undef_arg_begin(),
|
||||
CheckerState->undef_arg_end(),
|
||||
"Pass-by-value argument in function or message expression is undefined.");
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (Visualize) CheckerState->ViewGraph();
|
||||
|
|
|
@ -91,6 +91,7 @@ protected:
|
|||
typedef llvm::SmallPtrSet<NodeTy*,2> UndefStoresTy;
|
||||
typedef llvm::SmallPtrSet<NodeTy*,2> BadDerefTy;
|
||||
typedef llvm::SmallPtrSet<NodeTy*,2> BadCallsTy;
|
||||
typedef llvm::SmallPtrSet<NodeTy*,2> UndefArgsTy;
|
||||
typedef llvm::SmallPtrSet<NodeTy*,2> BadDividesTy;
|
||||
typedef llvm::SmallPtrSet<NodeTy*,2> NoReturnCallsTy;
|
||||
typedef llvm::SmallPtrSet<NodeTy*,2> UndefResultsTy;
|
||||
|
@ -132,6 +133,10 @@ protected:
|
|||
/// pointers that are NULL (or other constants) or Undefined.
|
||||
BadCallsTy BadCalls;
|
||||
|
||||
/// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
|
||||
/// where a pass-by-value argument has an undefined value.
|
||||
UndefArgsTy UndefArgs;
|
||||
|
||||
bool StateCleaned;
|
||||
|
||||
public:
|
||||
|
@ -203,6 +208,10 @@ public:
|
|||
return N->isSink() && BadCalls.count(const_cast<NodeTy*>(N)) != 0;
|
||||
}
|
||||
|
||||
bool isUndefArg(const NodeTy* N) const {
|
||||
return N->isSink() && UndefArgs.count(const_cast<NodeTy*>(N)) != 0;
|
||||
}
|
||||
|
||||
typedef BadDerefTy::iterator null_deref_iterator;
|
||||
null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
|
||||
null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
|
||||
|
@ -223,6 +232,10 @@ public:
|
|||
bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); }
|
||||
bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
|
||||
|
||||
typedef UndefArgsTy::iterator undef_arg_iterator;
|
||||
undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); }
|
||||
undef_arg_iterator undef_arg_end() { return UndefArgs.end(); }
|
||||
|
||||
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
|
||||
/// nodes by processing the 'effects' of a block-level statement.
|
||||
void ProcessStmt(Stmt* S, StmtNodeBuilder& builder);
|
||||
|
|
Loading…
Reference in New Issue