Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Taint.cpp
Line
Count
Source (jump to first uncovered line)
1
//=== Taint.cpp - Taint tracking and basic propagation rules. ------*- C++ -*-//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Defines basic, non-domain-specific mechanisms for tracking tainted values.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "Taint.h"
14
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
15
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
16
17
using namespace clang;
18
using namespace ento;
19
using namespace taint;
20
21
// Fully tainted symbols.
22
REGISTER_MAP_WITH_PROGRAMSTATE(TaintMap, SymbolRef, TaintTagType)
23
24
// Partially tainted symbols.
25
REGISTER_MAP_FACTORY_WITH_PROGRAMSTATE(TaintedSubRegions, const SubRegion *,
26
                                       TaintTagType)
27
REGISTER_MAP_WITH_PROGRAMSTATE(DerivedSymTaint, SymbolRef, TaintedSubRegions)
28
29
void taint::printTaint(ProgramStateRef State, raw_ostream &Out, const char *NL,
30
2
                       const char *Sep) {
31
2
  TaintMapTy TM = State->get<TaintMap>();
32
2
33
2
  if (!TM.isEmpty())
34
2
    Out << "Tainted symbols:" << NL;
35
2
36
2
  for (const auto &I : TM)
37
2
    Out << I.first << " : " << I.second << NL;
38
2
}
39
40
0
void dumpTaint(ProgramStateRef State) {
41
0
  printTaint(State, llvm::errs());
42
0
}
43
44
ProgramStateRef taint::addTaint(ProgramStateRef State, const Stmt *S,
45
                                const LocationContext *LCtx,
46
60
                                TaintTagType Kind) {
47
60
  return addTaint(State, State->getSVal(S, LCtx), Kind);
48
60
}
49
50
ProgramStateRef taint::addTaint(ProgramStateRef State, SVal V,
51
167
                                TaintTagType Kind) {
52
167
  SymbolRef Sym = V.getAsSymbol();
53
167
  if (Sym)
54
155
    return addTaint(State, Sym, Kind);
55
12
56
12
  // If the SVal represents a structure, try to mass-taint all values within the
57
12
  // structure. For now it only works efficiently on lazy compound values that
58
12
  // were conjured during a conservative evaluation of a function - either as
59
12
  // return values of functions that return structures or arrays by value, or as
60
12
  // values of structures or arrays passed into the function by reference,
61
12
  // directly or through pointer aliasing. Such lazy compound values are
62
12
  // characterized by having exactly one binding in their captured store within
63
12
  // their parent region, which is a conjured symbol default-bound to the base
64
12
  // region of the parent region.
65
12
  if (auto LCV = V.getAs<nonloc::LazyCompoundVal>()) {
66
12
    if (Optional<SVal> binding =
67
12
            State->getStateManager().getStoreManager()
68
12
                                    .getDefaultBinding(*LCV)) {
69
12
      if (SymbolRef Sym = binding->getAsSymbol())
70
12
        return addPartialTaint(State, Sym, LCV->getRegion(), Kind);
71
0
    }
72
12
  }
73
0
74
0
  const MemRegion *R = V.getAsRegion();
75
0
  return addTaint(State, R, Kind);
76
0
}
77
78
ProgramStateRef taint::addTaint(ProgramStateRef State, const MemRegion *R,
79
0
                                TaintTagType Kind) {
80
0
  if (const SymbolicRegion *SR = dyn_cast_or_null<SymbolicRegion>(R))
81
0
    return addTaint(State, SR->getSymbol(), Kind);
82
0
  return State;
83
0
}
84
85
ProgramStateRef taint::addTaint(ProgramStateRef State, SymbolRef Sym,
86
161
                                TaintTagType Kind) {
87
161
  // If this is a symbol cast, remove the cast before adding the taint. Taint
88
161
  // is cast agnostic.
89
161
  while (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
90
0
    Sym = SC->getOperand();
91
161
92
161
  ProgramStateRef NewState = State->set<TaintMap>(Sym, Kind);
93
161
  assert(NewState);
94
161
  return NewState;
95
161
}
96
97
ProgramStateRef taint::addPartialTaint(ProgramStateRef State,
98
                                       SymbolRef ParentSym,
99
                                       const SubRegion *SubRegion,
100
12
                                       TaintTagType Kind) {
101
12
  // Ignore partial taint if the entire parent symbol is already tainted.
102
12
  if (const TaintTagType *T = State->get<TaintMap>(ParentSym))
103
0
    if (*T == Kind)
104
0
      return State;
105
12
106
12
  // Partial taint applies if only a portion of the symbol is tainted.
107
12
  if (SubRegion == SubRegion->getBaseRegion())
108
6
    return addTaint(State, ParentSym, Kind);
109
6
110
6
  const TaintedSubRegions *SavedRegs = State->get<DerivedSymTaint>(ParentSym);
111
6
  TaintedSubRegions::Factory &F = State->get_context<TaintedSubRegions>();
112
6
  TaintedSubRegions Regs = SavedRegs ? 
*SavedRegs0
: F.getEmptyMap();
113
6
114
6
  Regs = F.add(Regs, SubRegion, Kind);
115
6
  ProgramStateRef NewState = State->set<DerivedSymTaint>(ParentSym, Regs);
116
6
  assert(NewState);
117
6
  return NewState;
118
6
}
119
120
bool taint::isTainted(ProgramStateRef State, const Stmt *S,
121
1.25k
                      const LocationContext *LCtx, TaintTagType Kind) {
122
1.25k
  SVal val = State->getSVal(S, LCtx);
123
1.25k
  return isTainted(State, val, Kind);
124
1.25k
}
125
126
11.0k
bool taint::isTainted(ProgramStateRef State, SVal V, TaintTagType Kind) {
127
11.0k
  if (const SymExpr *Sym = V.getAsSymExpr())
128
8.95k
    return isTainted(State, Sym, Kind);
129
2.10k
  if (const MemRegion *Reg = V.getAsRegion())
130
420
    return isTainted(State, Reg, Kind);
131
1.68k
  return false;
132
1.68k
}
133
134
bool taint::isTainted(ProgramStateRef State, const MemRegion *Reg,
135
4.15k
                      TaintTagType K) {
136
4.15k
  if (!Reg)
137
0
    return false;
138
4.15k
139
4.15k
  // Element region (array element) is tainted if either the base or the offset
140
4.15k
  // are tainted.
141
4.15k
  if (const ElementRegion *ER = dyn_cast<ElementRegion>(Reg))
142
1.20k
    return isTainted(State, ER->getSuperRegion(), K) ||
143
1.20k
           
isTainted(State, ER->getIndex(), K)1.06k
;
144
2.94k
145
2.94k
  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg))
146
1.02k
    return isTainted(State, SR->getSymbol(), K);
147
1.92k
148
1.92k
  if (const SubRegion *ER = dyn_cast<SubRegion>(Reg))
149
973
    return isTainted(State, ER->getSuperRegion(), K);
150
953
151
953
  return false;
152
953
}
153
154
12.6k
bool taint::isTainted(ProgramStateRef State, SymbolRef Sym, TaintTagType Kind) {
155
12.6k
  if (!Sym)
156
0
    return false;
157
12.6k
158
12.6k
  // Traverse all the symbols this symbol depends on to see if any are tainted.
159
12.6k
  for (SymExpr::symbol_iterator SI = Sym->symbol_begin(),
160
62.2k
                                SE = Sym->symbol_end(); SI != SE; 
++SI49.6k
) {
161
54.2k
    if (!isa<SymbolData>(*SI))
162
27.0k
      continue;
163
27.1k
164
27.1k
    if (const TaintTagType *Tag = State->get<TaintMap>(*SI)) {
165
4.03k
      if (*Tag == Kind)
166
4.03k
        return true;
167
23.0k
    }
168
23.0k
169
23.0k
    if (const auto *SD = dyn_cast<SymbolDerived>(*SI)) {
170
2.63k
      // If this is a SymbolDerived with a tainted parent, it's also tainted.
171
2.63k
      if (isTainted(State, SD->getParentSymbol(), Kind))
172
236
        return true;
173
2.39k
174
2.39k
      // If this is a SymbolDerived with the same parent symbol as another
175
2.39k
      // tainted SymbolDerived and a region that's a sub-region of that tainted
176
2.39k
      // symbol, it's also tainted.
177
2.39k
      if (const TaintedSubRegions *Regs =
178
108
              State->get<DerivedSymTaint>(SD->getParentSymbol())) {
179
108
        const TypedValueRegion *R = SD->getRegion();
180
108
        for (auto I : *Regs) {
181
108
          // FIXME: The logic to identify tainted regions could be more
182
108
          // complete. For example, this would not currently identify
183
108
          // overlapping fields in a union as tainted. To identify this we can
184
108
          // check for overlapping/nested byte offsets.
185
108
          if (Kind == I.second && R->isSubRegionOf(I.first))
186
98
            return true;
187
108
        }
188
108
      }
189
2.39k
    }
190
23.0k
191
23.0k
    // If memory region is tainted, data is also tainted.
192
23.0k
    
if (const auto *22.7k
SRV22.7k
= dyn_cast<SymbolRegionValue>(*SI)) {
193
1.55k
      if (isTainted(State, SRV->getRegion(), Kind))
194
142
        return true;
195
22.5k
    }
196
22.5k
197
22.5k
    // If this is a SymbolCast from a tainted value, it's also tainted.
198
22.5k
    if (const auto *SC = dyn_cast<SymbolCast>(*SI)) {
199
0
      if (isTainted(State, SC->getOperand(), Kind))
200
0
        return true;
201
0
    }
202
22.5k
  }
203
12.6k
204
12.6k
  
return false8.09k
;
205
12.6k
}
206
207
std::shared_ptr<PathDiagnosticPiece>
208
TaintBugVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
209
6.24k
                           BugReport &BR) {
210
6.24k
211
6.24k
  // Find the ExplodedNode where the taint was first introduced
212
6.24k
  if (!isTainted(N->getState(), V) ||
213
6.24k
      
isTainted(N->getFirstPred()->getState(), V)1.99k
)
214
6.17k
    return nullptr;
215
68
216
68
  const Stmt *S = PathDiagnosticLocation::getStmt(N);
217
68
  if (!S)
218
0
    return nullptr;
219
68
220
68
  const LocationContext *NCtx = N->getLocationContext();
221
68
  PathDiagnosticLocation L =
222
68
      PathDiagnosticLocation::createBegin(S, BRC.getSourceManager(), NCtx);
223
68
  if (!L.isValid() || !L.asLocation().isValid())
224
0
    return nullptr;
225
68
226
68
  return std::make_shared<PathDiagnosticEventPiece>(L, "Taint originated here");
227
68
}