From b86fdbe7e38a4e71cdda12cce2253e1f3235743a Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Wed, 7 Dec 2011 01:09:52 +0000 Subject: [PATCH] [analyzer] Propagate taint through MemRegions. SVal can be not only a symbol, but a MemRegion. Add support for such cases. llvm-svn: 146006 --- .../Core/PathSensitive/ProgramState.h | 1 + .../lib/StaticAnalyzer/Core/ProgramState.cpp | 27 +++++++++++++++++-- clang/test/Analysis/taint-tester.c | 19 ++++++++++--- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 8b646f42744a..242b49e75f50 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -301,6 +301,7 @@ public: bool isTainted(const Stmt *S, TaintTagType Kind = TaintTagGeneric) const; bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const; bool isTainted(const SymExpr* Sym, TaintTagType Kind = TaintTagGeneric) const; + bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const; //==---------------------------------------------------------------------==// // Accessing the Generic Data Map (GDM). diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index 2f9a3929e8a8..bad14c459bb8 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -664,18 +664,41 @@ const ProgramState* ProgramState::addTaint(SymbolRef Sym, } bool ProgramState::isTainted(const Stmt *S, TaintTagType Kind) const { + SVal val = getSVal(S); return isTainted(getSVal(S), Kind); } bool ProgramState::isTainted(SVal V, TaintTagType Kind) const { - return isTainted(V.getAsSymExpr(), Kind); + if (const SymExpr *Sym = V.getAsSymExpr()) + return isTainted(Sym, Kind); + if (loc::MemRegionVal *RegVal = dyn_cast(&V)) + return isTainted(RegVal->getRegion(), Kind); + return false; +} + +bool ProgramState::isTainted(const MemRegion *Reg, TaintTagType K) const { + if (!Reg) + return false; + + // Element region (array element) is tainted if either the base or the offset + // are tainted. + if (const ElementRegion *ER = dyn_cast(Reg)) + return isTainted(ER->getSuperRegion(), K) || isTainted(ER->getIndex(), K); + + if (const SymbolicRegion *SR = dyn_cast(Reg)) + return isTainted(SR->getSymbol(), K); + + if (const SubRegion *ER = dyn_cast(Reg)) + return isTainted(ER->getSuperRegion(), K); + + return false; } bool ProgramState::isTainted(const SymExpr* Sym, TaintTagType Kind) const { if (!Sym) return false; - // Travese all the symbols this symbol depends on to see if any are tainted. + // Traverse all the symbols this symbol depends on to see if any are tainted. bool Tainted = false; for (SymExpr::symbol_iterator SI = Sym->symbol_begin(), SE =Sym->symbol_end(); SI != SE; ++SI) { diff --git a/clang/test/Analysis/taint-tester.c b/clang/test/Analysis/taint-tester.c index eb05f577d1b7..23b5744f8c84 100644 --- a/clang/test/Analysis/taint-tester.c +++ b/clang/test/Analysis/taint-tester.c @@ -6,18 +6,29 @@ int getchar(void); #define BUFSIZE 10 int Buffer[BUFSIZE]; -void bufferScanfAssignment(int x) { +struct XYStruct { + int x; + float y; +}; + +void taintTracking(int x) { int n; int *addr = &Buffer[0]; scanf("%d", &n); - addr += n;// expected-warning {{tainted}} - *addr = n; // expected-warning 2 {{tainted}} + addr += n;// expected-warning 2 {{tainted}} + *addr = n; // expected-warning 3 {{tainted}} double tdiv = n / 30; // expected-warning 3 {{tainted}} char *loc_cast = (char *) n; // expected-warning {{tainted}} char tinc = tdiv++; // expected-warning {{tainted}} int tincdec = (char)tinc--; // expected-warning 2 {{tainted}} - int tprtarithmetic1 = *(addr+1); + // Tainted ptr arithmetic/array element address. + int tprtarithmetic1 = *(addr+1); // expected-warning 2 {{tainted}} + // Tainted struct address, casts. + struct XYStruct *xyPtr = 0; + scanf("%p", &xyPtr); + void *tXYStructPtr = xyPtr; // expected-warning 2 {{tainted}} + struct XYStruct *xyPtrCopy = tXYStructPtr; // expected-warning 2 {{tainted}} }