aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2011-12-14 00:56:18 +0000
committerAnna Zaks <ganna@apple.com>2011-12-14 00:56:18 +0000
commitefd6989f4644c8460854606e085fc69535054058 (patch)
treecdfefd4756583ef38abfd8a881269d890157851c /lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
parent28fd98d66dab4569316de2b5881d91b534a42461 (diff)
[analyzer] Treat stdin as a source of taint.
Some of the test cases do not currently work because the analyzer core does not seem to call checkers for pre/post DeclRefExpr visits. (Opened radar://10573500. To be fixed later on.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146536 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp50
1 files changed, 44 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 890a592c17..739287284b 100644
--- a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -24,7 +24,8 @@ using namespace clang;
using namespace ento;
namespace {
-class GenericTaintChecker : public Checker< check::PostStmt<CallExpr> > {
+class GenericTaintChecker : public Checker< check::PostStmt<CallExpr>,
+ check::PostStmt<DeclRefExpr> > {
mutable llvm::OwningPtr<BugType> BT;
void initBugType() const;
@@ -42,8 +43,12 @@ class GenericTaintChecker : public Checker< check::PostStmt<CallExpr> > {
void processFscanf(const CallExpr *CE, CheckerContext &C) const;
void processRetTaint(const CallExpr *CE, CheckerContext &C) const;
+ bool isStdin(const Expr *E, CheckerContext &C) const;
+ bool isStdin(const DeclRefExpr *E, CheckerContext &C) const;
+
public:
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPostStmt(const DeclRefExpr *DRE, CheckerContext &C) const;
};
}
@@ -77,18 +82,28 @@ void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
// Check and evaluate the call.
if (evalFunction)
(this->*evalFunction)(CE, C);
+}
+void GenericTaintChecker::checkPostStmt(const DeclRefExpr *DRE,
+ CheckerContext &C) const {
+ if (isStdin(DRE, C)) {
+ const ProgramState *NewState = C.getState()->addTaint(DRE);
+ C.addTransition(NewState);
+ }
}
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->IgnoreParens());
- // TODO: Taint is not going to propagate?
- if (AddrVal.isUnknownOrUndef())
+ // TODO: Taint is not going to propagate? Should we ever peel off the casts
+ // IgnoreParenImpCasts()?
+ if (AddrVal.isUnknownOrUndef()) {
+ assert(State->getSVal(Arg->IgnoreParenImpCasts()).isUnknownOrUndef());
return 0;
+ }
Loc *AddrLoc = dyn_cast<Loc>(&AddrVal);
@@ -111,7 +126,6 @@ SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
return Val.getAsSymbol();
}
-
void GenericTaintChecker::processScanf(const CallExpr *CE,
CheckerContext &C) const {
const ProgramState *State = C.getState();
@@ -137,7 +151,7 @@ void GenericTaintChecker::processFscanf(const CallExpr *CE,
assert(CE->getNumArgs() >= 2);
// Check is the file descriptor is tainted.
- if (!State->isTainted(CE->getArg(0)))
+ if (!State->isTainted(CE->getArg(0)) && !isStdin(CE->getArg(0), C))
return;
// All arguments except for the first two should get taint.
@@ -158,6 +172,30 @@ void GenericTaintChecker::processRetTaint(const CallExpr *CE,
C.addTransition(NewState);
}
+bool GenericTaintChecker::isStdin(const Expr *E,
+ CheckerContext &C) const {
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+ return isStdin(DR, C);
+ return false;
+}
+
+bool GenericTaintChecker::isStdin(const DeclRefExpr *DR,
+ CheckerContext &C) const {
+ const VarDecl *D = dyn_cast_or_null<VarDecl>(DR->getDecl());
+ if (!D)
+ return false;
+
+ D = D->getCanonicalDecl();
+ if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC())
+ if (const PointerType * PtrTy =
+ dyn_cast<PointerType>(D->getType().getTypePtr()))
+ if (PtrTy->getPointeeType() == C.getASTContext().getFILEType())
+ return true;
+
+ return false;
+}
+
+
void ento::registerGenericTaintChecker(CheckerManager &mgr) {
mgr.registerChecker<GenericTaintChecker>();
}