forked from OSchip/llvm-project
[analyzer] Warn when non pointer arguments are passed to scanf (only when running taint checker).
There is an open radar to implement better scanf checking as a Sema warning. However, a bit of redundancy is fine in this case. llvm-svn: 144964
This commit is contained in:
parent
1d7dd3b682
commit
457c68726c
|
@ -26,7 +26,14 @@ using namespace ento;
|
|||
namespace {
|
||||
class GenericTaintChecker : public Checker< check::PostStmt<CallExpr> > {
|
||||
|
||||
mutable llvm::OwningPtr<BuiltinBug> BT;
|
||||
mutable llvm::OwningPtr<BugType> BT;
|
||||
void initBugType() const;
|
||||
|
||||
/// Given a pointer argument, get the symbol of the value it contains
|
||||
/// (points to).
|
||||
SymbolRef getPointedToSymbol(CheckerContext &C,
|
||||
const Expr* Arg,
|
||||
bool IssueWarning = true) const;
|
||||
|
||||
/// Functions defining the attacke surface.
|
||||
typedef void (GenericTaintChecker::*FnCheck)(const CallExpr *,
|
||||
|
@ -39,6 +46,11 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
inline void GenericTaintChecker::initBugType() const {
|
||||
if (!BT)
|
||||
BT.reset(new BugType("Tainted data checking", "General"));
|
||||
}
|
||||
|
||||
void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
if (!C.getState())
|
||||
|
@ -59,10 +71,29 @@ void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
|
|||
(this->*evalFunction)(CE, C);
|
||||
|
||||
}
|
||||
static SymbolRef getPointedToSymbol(const ProgramState *State,
|
||||
const Expr* Arg) {
|
||||
|
||||
SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
|
||||
const Expr* Arg,
|
||||
bool IssueWarning) const {
|
||||
const ProgramState *State = C.getState();
|
||||
SVal AddrVal = State->getSVal(Arg->IgnoreParenCasts());
|
||||
Loc *AddrLoc = dyn_cast<Loc>(&AddrVal);
|
||||
|
||||
if (!AddrLoc && !IssueWarning)
|
||||
return 0;
|
||||
|
||||
// If the Expr is not a location, issue a warning.
|
||||
if (!AddrLoc) {
|
||||
assert(IssueWarning);
|
||||
if (ExplodedNode *N = C.generateSink(State)) {
|
||||
initBugType();
|
||||
BugReport *report = new BugReport(*BT, "Pointer argument is expected.",N);
|
||||
report->addRange(Arg->getSourceRange());
|
||||
C.EmitReport(report);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SVal Val = State->getSVal(*AddrLoc);
|
||||
return Val.getAsSymbol();
|
||||
}
|
||||
|
@ -78,7 +109,7 @@ void GenericTaintChecker::processScanf(const CallExpr *CE,
|
|||
// The arguments are pointer arguments. The data they are pointing at is
|
||||
// tainted after the call.
|
||||
const Expr* Arg = CE->getArg(i);
|
||||
SymbolRef Sym = getPointedToSymbol(State, Arg);
|
||||
SymbolRef Sym = getPointedToSymbol(C, Arg);
|
||||
if (Sym)
|
||||
State = State->addTaint(Sym);
|
||||
}
|
||||
|
|
|
@ -177,7 +177,6 @@ SVal SValBuilder::generateUnknownVal(const ProgramState *State,
|
|||
symLHS = LHS.getAsSymExpr();
|
||||
return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
|
||||
}
|
||||
// TODO: Handle the case when lhs is ConcreteInt.
|
||||
|
||||
symLHS = LHS.getAsSymExpr();
|
||||
symRHS = RHS.getAsSymExpr();
|
||||
|
|
|
@ -26,3 +26,8 @@ void bufferScanfArithmetic2(int x) {
|
|||
int m = (n + 3) * x;
|
||||
Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
|
||||
}
|
||||
|
||||
void scanfArg() {
|
||||
int t;
|
||||
scanf("%d", t); // expected-warning {{Pointer argument is expected}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue