aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2011-12-16 18:28:50 +0000
committerAnna Zaks <ganna@apple.com>2011-12-16 18:28:50 +0000
commitd3d8548e75f3fb6db53ed0927c1df30d78f4ce1d (patch)
tree75726ad7899c12c78864dcae3018af68407f2e77 /lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
parent0e818a412f337baa35d1d7677c64259610df0c2e (diff)
[analyzer] Better stdin support.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146748 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp50
1 files changed, 28 insertions, 22 deletions
diff --git a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 739287284b..8cdd89b1c4 100644
--- a/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -43,8 +43,9 @@ class GenericTaintChecker : public Checker< check::PostStmt<CallExpr>,
void processFscanf(const CallExpr *CE, CheckerContext &C) const;
void processRetTaint(const CallExpr *CE, CheckerContext &C) const;
+ /// Check if the region the expression evaluates to is the standard input,
+ /// and thus, is tainted.
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;
@@ -97,13 +98,8 @@ SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
bool IssueWarning) const {
const ProgramState *State = C.getState();
SVal AddrVal = State->getSVal(Arg->IgnoreParens());
-
- // TODO: Taint is not going to propagate? Should we ever peel off the casts
- // IgnoreParenImpCasts()?
- if (AddrVal.isUnknownOrUndef()) {
- assert(State->getSVal(Arg->IgnoreParenImpCasts()).isUnknownOrUndef());
+ if (AddrVal.isUnknownOrUndef())
return 0;
- }
Loc *AddrLoc = dyn_cast<Loc>(&AddrVal);
@@ -174,28 +170,38 @@ void GenericTaintChecker::processRetTaint(const CallExpr *CE,
bool GenericTaintChecker::isStdin(const Expr *E,
CheckerContext &C) const {
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
- return isStdin(DR, C);
- return false;
-}
+ const ProgramState *State = C.getState();
+ SVal Val = State->getSVal(E);
-bool GenericTaintChecker::isStdin(const DeclRefExpr *DR,
- CheckerContext &C) const {
- const VarDecl *D = dyn_cast_or_null<VarDecl>(DR->getDecl());
- if (!D)
+ // stdin is a pointer, so it would be a region.
+ const MemRegion *MemReg = Val.getAsRegion();
+
+ // The region should be symbolic, we do not know it's value.
+ const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg);
+ if (!SymReg)
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;
+ // Get it's symbol and find the declaration region it's pointing to.
+ const SymbolRegionValue *Sm =dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
+ if (!Sm)
+ return false;
+ const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
+ if (!DeclReg)
+ return false;
+ // This region corresponds to a declaration, find out if it's a global/extern
+ // variable named stdin with the proper type.
+ if (const VarDecl *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
+ 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>();
}