Visit Stmt children for null deref check.

The previous version of the Null deref visitor was defaulting to
VisitStmt when the Stmt type was unknown, thus allowing for some
types of Stmt X for which a VisitX was not implemented to default
to VisitStmt and not check the content of it. In order to check
any type of Stmt for possible subexpressions which contain s Stmt
that derefrences a Null, the VisitStmt was extended to check its
children.

Only the Stmt types, X, which directly containing a null deref expression
have an explicit VisitX with the exception of CXXMemberCallExpr,
because this type would otherwise default to VisitCallExpr which has
a different check for its structure.
This commit is contained in:
CristinaCristescu 2016-01-13 14:47:43 +01:00 committed by sftnight
parent abf65cb689
commit 94dd1ea523

View File

@ -107,6 +107,11 @@ namespace cling {
}
NodeContext VisitStmt(Stmt* S) {
for (auto I = S->child_begin(), E = S->child_end(); I != E; ++I) {
if (*I)
NodeContext nc = Visit(*I);
}
return NodeContext(S);
}
@ -122,79 +127,42 @@ namespace cling {
stmts.append(nc.getStmts().begin(), nc.getStmts().end());
}
llvm::ArrayRef<Stmt*> stmtsRef(stmts.data(), stmts.size());
CompoundStmt* newCS = new (C) CompoundStmt(C, stmtsRef,
CS->getLBracLoc(),
CS->getRBracLoc());
return NodeContext(newCS);
}
if (!stmts.empty()) {
llvm::ArrayRef<Stmt*> stmtsRef(stmts.data(), stmts.size());
CS->setStmts(C, const_cast<Stmt**>(&stmtsRef.front()), stmts.size());
}
NodeContext VisitIfStmt(IfStmt* If) {
// check the condition
NodeContext cond = Visit(If->getCond());
if (!cond.isSingleStmt())
If->setCond((clang::Expr*)cond.getStmt());
// No default constructor..
NodeContext result(If);
return result;
}
NodeContext VisitCastExpr(CastExpr* CE) {
NodeContext castExpr = Visit(CE->getSubExpr());
if (castExpr.isSingleStmt())
CE->setSubExpr((clang::Expr*)castExpr.getStmt());
// No default constructor..
NodeContext result(CE);
return result;
return NodeContext(CS);
}
NodeContext VisitUnaryOperator(UnaryOperator* UnOp) {
if (UnOp->getOpcode() == UO_Deref) {
UnOp->setSubExpr((clang::Expr*)SynthesizeCheck(UnOp->getLocStart(),
UnOp->getSubExpr()));
NodeContext newSubExpr = SynthesizeCheck(UnOp->getLocStart(),
UnOp->getSubExpr());
if (newSubExpr.isSingleStmt()) {
assert ((clang::Expr*)newSubExpr.getStmt()
&& "Visiting Stmt which is not an Expr!");
UnOp->setSubExpr((clang::Expr*)newSubExpr.getStmt());
}
}
// No default constructor..
NodeContext result(UnOp);
return result;
}
NodeContext VisitBinaryOperator(BinaryOperator* BinOp) {
// Here we might get if(check) throw; binop rhs.
NodeContext rhs = Visit(BinOp->getRHS());
// Here we might get if(check) throw; binop lhs.
NodeContext lhs = Visit(BinOp->getLHS());
if (rhs.isSingleStmt()) {
// FIXME:we need to loop from 0 to n-1
BinOp->setRHS((clang::Expr*)rhs.getStmt());
}
if (lhs.isSingleStmt()) {
// FIXME:we need to loop from 0 to n-1
BinOp->setLHS((clang::Expr*)lhs.getStmt());
}
// No default constructor..
NodeContext result(BinOp);
return result;
return NodeContext(UnOp);
}
NodeContext VisitMemberExpr(MemberExpr* ME) {
if (ME->isArrow()) {
NodeContext newBase = SynthesizeCheck(ME->getLocStart(), ME->getBase());
if (newBase.isSingleStmt())
assert ((clang::Expr*)newBase.getStmt()
&& "Visiting Stmt which is not an Expr!");
ME->setBase((clang::Expr*)newBase.getStmt());
}
NodeContext result(ME);
return result;
return NodeContext(ME);
}
NodeContext VisitCallExpr(CallExpr* CE) {
FunctionDecl* FDecl = CE->getDirectCallee();
NodeContext result(CE);
if (FDecl && isDeclCandidate(FDecl)) {
decl_map_t::const_iterator it = m_NonNullArgIndexs.find(FDecl);
const std::bitset<32>& ArgIndexs = it->second;
@ -203,24 +171,31 @@ namespace cling {
if (ArgIndexs.test(index)) {
// Get the argument with the nonnull attribute.
Expr* Arg = CE->getArg(index);
NodeContext newArg = SynthesizeCheck(Arg->getLocStart(), Arg);
if (newArg.isSingleStmt()) {
assert ((clang::Expr*)newArg.getStmt()
&& "Visiting Stmt which is NodeContext an Expr!");
CE->setArg(index,
(clang::Expr*)SynthesizeCheck(Arg->getLocStart(), Arg));
(clang::Expr*)newArg.getStmt());
}
}
}
}
return result;
return NodeContext(CE);
}
NodeContext VisitCXXMemberCallExpr(CXXMemberCallExpr* CME) {
Expr* Callee = CME->getCallee();
if (isa<MemberExpr>(Callee)) {
NodeContext ME = Visit(Callee);
if (!ME.isSingleStmt())
CME->setCallee((clang::Expr*)ME.getStmt());
NodeContext newME = Visit(Callee);
if (newME.isSingleStmt())
assert ((clang::Expr*)newME.getStmt()
&& "Visiting Stmt which is not an Expr!");
CME->setCallee((clang::Expr*)newME.getStmt());
}
NodeContext result(CME);
return result;
return NodeContext(CME);
}
private: