Added extra check for calls to functions where we pass undefined values

as arguments.

llvm-svn: 47778
This commit is contained in:
Ted Kremenek 2008-02-29 23:53:11 +00:00
parent e8ddaba169
commit 51e87ea210
3 changed files with 42 additions and 4 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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);