Skip to content
Snippets Groups Projects
Commit 8f4caf5f authored by Anna Zaks's avatar Anna Zaks
Browse files

[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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144964 91177308-0d34-0410-b5e6-96231b3b80d8
parent 7b1fb81a
No related branches found
No related tags found
Loading
...@@ -26,7 +26,14 @@ using namespace ento; ...@@ -26,7 +26,14 @@ using namespace ento;
namespace { namespace {
class GenericTaintChecker : public Checker< check::PostStmt<CallExpr> > { 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. /// Functions defining the attacke surface.
typedef void (GenericTaintChecker::*FnCheck)(const CallExpr *, typedef void (GenericTaintChecker::*FnCheck)(const CallExpr *,
...@@ -39,6 +46,11 @@ public: ...@@ -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, void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
CheckerContext &C) const { CheckerContext &C) const {
if (!C.getState()) if (!C.getState())
...@@ -59,10 +71,29 @@ void GenericTaintChecker::checkPostStmt(const CallExpr *CE, ...@@ -59,10 +71,29 @@ void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
(this->*evalFunction)(CE, C); (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()); SVal AddrVal = State->getSVal(Arg->IgnoreParenCasts());
Loc *AddrLoc = dyn_cast<Loc>(&AddrVal); 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); SVal Val = State->getSVal(*AddrLoc);
return Val.getAsSymbol(); return Val.getAsSymbol();
} }
...@@ -78,7 +109,7 @@ void GenericTaintChecker::processScanf(const CallExpr *CE, ...@@ -78,7 +109,7 @@ void GenericTaintChecker::processScanf(const CallExpr *CE,
// The arguments are pointer arguments. The data they are pointing at is // The arguments are pointer arguments. The data they are pointing at is
// tainted after the call. // tainted after the call.
const Expr* Arg = CE->getArg(i); const Expr* Arg = CE->getArg(i);
SymbolRef Sym = getPointedToSymbol(State, Arg); SymbolRef Sym = getPointedToSymbol(C, Arg);
if (Sym) if (Sym)
State = State->addTaint(Sym); State = State->addTaint(Sym);
} }
......
...@@ -177,7 +177,6 @@ SVal SValBuilder::generateUnknownVal(const ProgramState *State, ...@@ -177,7 +177,6 @@ SVal SValBuilder::generateUnknownVal(const ProgramState *State,
symLHS = LHS.getAsSymExpr(); symLHS = LHS.getAsSymExpr();
return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy); return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
} }
// TODO: Handle the case when lhs is ConcreteInt.
symLHS = LHS.getAsSymExpr(); symLHS = LHS.getAsSymExpr();
symRHS = RHS.getAsSymExpr(); symRHS = RHS.getAsSymExpr();
......
...@@ -26,3 +26,8 @@ void bufferScanfArithmetic2(int x) { ...@@ -26,3 +26,8 @@ void bufferScanfArithmetic2(int x) {
int m = (n + 3) * x; int m = (n + 3) * x;
Buffer[m] = 1; // expected-warning {{Out of bound memory access }} Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
} }
void scanfArg() {
int t;
scanf("%d", t); // expected-warning {{Pointer argument is expected}}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment