xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/Taint.cpp (revision 6c4b055cfb6bf549e9145dde6454cc6b178c35e4)
10b57cec5SDimitry Andric //=== Taint.cpp - Taint tracking and basic propagation rules. ------*- C++ -*-//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Defines basic, non-domain-specific mechanisms for tracking tainted values.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
1381ad6265SDimitry Andric #include "clang/StaticAnalyzer/Checkers/Taint.h"
140b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
15*6c4b055cSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
160b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
17bdd1243dSDimitry Andric #include <optional>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric using namespace clang;
200b57cec5SDimitry Andric using namespace ento;
210b57cec5SDimitry Andric using namespace taint;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric // Fully tainted symbols.
240b57cec5SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(TaintMap, SymbolRef, TaintTagType)
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric // Partially tainted symbols.
270b57cec5SDimitry Andric REGISTER_MAP_FACTORY_WITH_PROGRAMSTATE(TaintedSubRegions, const SubRegion *,
280b57cec5SDimitry Andric                                        TaintTagType)
290b57cec5SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(DerivedSymTaint, SymbolRef, TaintedSubRegions)
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric void taint::printTaint(ProgramStateRef State, raw_ostream &Out, const char *NL,
320b57cec5SDimitry Andric                        const char *Sep) {
330b57cec5SDimitry Andric   TaintMapTy TM = State->get<TaintMap>();
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   if (!TM.isEmpty())
360b57cec5SDimitry Andric     Out << "Tainted symbols:" << NL;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   for (const auto &I : TM)
390b57cec5SDimitry Andric     Out << I.first << " : " << I.second << NL;
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric 
4281ad6265SDimitry Andric void taint::dumpTaint(ProgramStateRef State) {
4381ad6265SDimitry Andric   printTaint(State, llvm::errs());
4481ad6265SDimitry Andric }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric ProgramStateRef taint::addTaint(ProgramStateRef State, const Stmt *S,
470b57cec5SDimitry Andric                                 const LocationContext *LCtx,
480b57cec5SDimitry Andric                                 TaintTagType Kind) {
490b57cec5SDimitry Andric   return addTaint(State, State->getSVal(S, LCtx), Kind);
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric ProgramStateRef taint::addTaint(ProgramStateRef State, SVal V,
530b57cec5SDimitry Andric                                 TaintTagType Kind) {
540b57cec5SDimitry Andric   SymbolRef Sym = V.getAsSymbol();
550b57cec5SDimitry Andric   if (Sym)
560b57cec5SDimitry Andric     return addTaint(State, Sym, Kind);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   // If the SVal represents a structure, try to mass-taint all values within the
590b57cec5SDimitry Andric   // structure. For now it only works efficiently on lazy compound values that
600b57cec5SDimitry Andric   // were conjured during a conservative evaluation of a function - either as
610b57cec5SDimitry Andric   // return values of functions that return structures or arrays by value, or as
620b57cec5SDimitry Andric   // values of structures or arrays passed into the function by reference,
630b57cec5SDimitry Andric   // directly or through pointer aliasing. Such lazy compound values are
640b57cec5SDimitry Andric   // characterized by having exactly one binding in their captured store within
650b57cec5SDimitry Andric   // their parent region, which is a conjured symbol default-bound to the base
660b57cec5SDimitry Andric   // region of the parent region.
670b57cec5SDimitry Andric   if (auto LCV = V.getAs<nonloc::LazyCompoundVal>()) {
68bdd1243dSDimitry Andric     if (std::optional<SVal> binding =
69480093f4SDimitry Andric             State->getStateManager().getStoreManager().getDefaultBinding(
70480093f4SDimitry Andric                 *LCV)) {
710b57cec5SDimitry Andric       if (SymbolRef Sym = binding->getAsSymbol())
720b57cec5SDimitry Andric         return addPartialTaint(State, Sym, LCV->getRegion(), Kind);
730b57cec5SDimitry Andric     }
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   const MemRegion *R = V.getAsRegion();
770b57cec5SDimitry Andric   return addTaint(State, R, Kind);
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric ProgramStateRef taint::addTaint(ProgramStateRef State, const MemRegion *R,
810b57cec5SDimitry Andric                                 TaintTagType Kind) {
820b57cec5SDimitry Andric   if (const SymbolicRegion *SR = dyn_cast_or_null<SymbolicRegion>(R))
830b57cec5SDimitry Andric     return addTaint(State, SR->getSymbol(), Kind);
840b57cec5SDimitry Andric   return State;
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric ProgramStateRef taint::addTaint(ProgramStateRef State, SymbolRef Sym,
880b57cec5SDimitry Andric                                 TaintTagType Kind) {
890b57cec5SDimitry Andric   // If this is a symbol cast, remove the cast before adding the taint. Taint
900b57cec5SDimitry Andric   // is cast agnostic.
910b57cec5SDimitry Andric   while (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
920b57cec5SDimitry Andric     Sym = SC->getOperand();
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   ProgramStateRef NewState = State->set<TaintMap>(Sym, Kind);
950b57cec5SDimitry Andric   assert(NewState);
960b57cec5SDimitry Andric   return NewState;
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
99480093f4SDimitry Andric ProgramStateRef taint::removeTaint(ProgramStateRef State, SVal V) {
100480093f4SDimitry Andric   SymbolRef Sym = V.getAsSymbol();
101480093f4SDimitry Andric   if (Sym)
102480093f4SDimitry Andric     return removeTaint(State, Sym);
103480093f4SDimitry Andric 
104480093f4SDimitry Andric   const MemRegion *R = V.getAsRegion();
105480093f4SDimitry Andric   return removeTaint(State, R);
106480093f4SDimitry Andric }
107480093f4SDimitry Andric 
108480093f4SDimitry Andric ProgramStateRef taint::removeTaint(ProgramStateRef State, const MemRegion *R) {
109480093f4SDimitry Andric   if (const SymbolicRegion *SR = dyn_cast_or_null<SymbolicRegion>(R))
110480093f4SDimitry Andric     return removeTaint(State, SR->getSymbol());
111480093f4SDimitry Andric   return State;
112480093f4SDimitry Andric }
113480093f4SDimitry Andric 
114480093f4SDimitry Andric ProgramStateRef taint::removeTaint(ProgramStateRef State, SymbolRef Sym) {
115480093f4SDimitry Andric   // If this is a symbol cast, remove the cast before adding the taint. Taint
116480093f4SDimitry Andric   // is cast agnostic.
117480093f4SDimitry Andric   while (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
118480093f4SDimitry Andric     Sym = SC->getOperand();
119480093f4SDimitry Andric 
120480093f4SDimitry Andric   ProgramStateRef NewState = State->remove<TaintMap>(Sym);
121480093f4SDimitry Andric   assert(NewState);
122480093f4SDimitry Andric   return NewState;
123480093f4SDimitry Andric }
124480093f4SDimitry Andric 
1250b57cec5SDimitry Andric ProgramStateRef taint::addPartialTaint(ProgramStateRef State,
1260b57cec5SDimitry Andric                                        SymbolRef ParentSym,
1270b57cec5SDimitry Andric                                        const SubRegion *SubRegion,
1280b57cec5SDimitry Andric                                        TaintTagType Kind) {
1290b57cec5SDimitry Andric   // Ignore partial taint if the entire parent symbol is already tainted.
1300b57cec5SDimitry Andric   if (const TaintTagType *T = State->get<TaintMap>(ParentSym))
1310b57cec5SDimitry Andric     if (*T == Kind)
1320b57cec5SDimitry Andric       return State;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   // Partial taint applies if only a portion of the symbol is tainted.
1350b57cec5SDimitry Andric   if (SubRegion == SubRegion->getBaseRegion())
1360b57cec5SDimitry Andric     return addTaint(State, ParentSym, Kind);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   const TaintedSubRegions *SavedRegs = State->get<DerivedSymTaint>(ParentSym);
1390b57cec5SDimitry Andric   TaintedSubRegions::Factory &F = State->get_context<TaintedSubRegions>();
1400b57cec5SDimitry Andric   TaintedSubRegions Regs = SavedRegs ? *SavedRegs : F.getEmptyMap();
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   Regs = F.add(Regs, SubRegion, Kind);
1430b57cec5SDimitry Andric   ProgramStateRef NewState = State->set<DerivedSymTaint>(ParentSym, Regs);
1440b57cec5SDimitry Andric   assert(NewState);
1450b57cec5SDimitry Andric   return NewState;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric bool taint::isTainted(ProgramStateRef State, const Stmt *S,
1490b57cec5SDimitry Andric                       const LocationContext *LCtx, TaintTagType Kind) {
15006c3fb27SDimitry Andric   return !getTaintedSymbolsImpl(State, S, LCtx, Kind, /*ReturnFirstOnly=*/true)
15106c3fb27SDimitry Andric               .empty();
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric bool taint::isTainted(ProgramStateRef State, SVal V, TaintTagType Kind) {
15506c3fb27SDimitry Andric   return !getTaintedSymbolsImpl(State, V, Kind, /*ReturnFirstOnly=*/true)
15606c3fb27SDimitry Andric               .empty();
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric bool taint::isTainted(ProgramStateRef State, const MemRegion *Reg,
1600b57cec5SDimitry Andric                       TaintTagType K) {
16106c3fb27SDimitry Andric   return !getTaintedSymbolsImpl(State, Reg, K, /*ReturnFirstOnly=*/true)
16206c3fb27SDimitry Andric               .empty();
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric bool taint::isTainted(ProgramStateRef State, SymbolRef Sym, TaintTagType Kind) {
16606c3fb27SDimitry Andric   return !getTaintedSymbolsImpl(State, Sym, Kind, /*ReturnFirstOnly=*/true)
16706c3fb27SDimitry Andric               .empty();
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
17006c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbols(ProgramStateRef State,
17106c3fb27SDimitry Andric                                                 const Stmt *S,
17206c3fb27SDimitry Andric                                                 const LocationContext *LCtx,
17306c3fb27SDimitry Andric                                                 TaintTagType Kind) {
17406c3fb27SDimitry Andric   return getTaintedSymbolsImpl(State, S, LCtx, Kind, /*ReturnFirstOnly=*/false);
17506c3fb27SDimitry Andric }
17606c3fb27SDimitry Andric 
17706c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbols(ProgramStateRef State, SVal V,
17806c3fb27SDimitry Andric                                                 TaintTagType Kind) {
17906c3fb27SDimitry Andric   return getTaintedSymbolsImpl(State, V, Kind, /*ReturnFirstOnly=*/false);
18006c3fb27SDimitry Andric }
18106c3fb27SDimitry Andric 
18206c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbols(ProgramStateRef State,
18306c3fb27SDimitry Andric                                                 SymbolRef Sym,
18406c3fb27SDimitry Andric                                                 TaintTagType Kind) {
18506c3fb27SDimitry Andric   return getTaintedSymbolsImpl(State, Sym, Kind, /*ReturnFirstOnly=*/false);
18606c3fb27SDimitry Andric }
18706c3fb27SDimitry Andric 
18806c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbols(ProgramStateRef State,
18906c3fb27SDimitry Andric                                                 const MemRegion *Reg,
19006c3fb27SDimitry Andric                                                 TaintTagType Kind) {
19106c3fb27SDimitry Andric   return getTaintedSymbolsImpl(State, Reg, Kind, /*ReturnFirstOnly=*/false);
19206c3fb27SDimitry Andric }
19306c3fb27SDimitry Andric 
19406c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
19506c3fb27SDimitry Andric                                                     const Stmt *S,
19606c3fb27SDimitry Andric                                                     const LocationContext *LCtx,
19706c3fb27SDimitry Andric                                                     TaintTagType Kind,
19806c3fb27SDimitry Andric                                                     bool returnFirstOnly) {
19906c3fb27SDimitry Andric   SVal val = State->getSVal(S, LCtx);
20006c3fb27SDimitry Andric   return getTaintedSymbolsImpl(State, val, Kind, returnFirstOnly);
20106c3fb27SDimitry Andric }
20206c3fb27SDimitry Andric 
20306c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
20406c3fb27SDimitry Andric                                                     SVal V, TaintTagType Kind,
20506c3fb27SDimitry Andric                                                     bool returnFirstOnly) {
20606c3fb27SDimitry Andric   if (SymbolRef Sym = V.getAsSymbol())
20706c3fb27SDimitry Andric     return getTaintedSymbolsImpl(State, Sym, Kind, returnFirstOnly);
20806c3fb27SDimitry Andric   if (const MemRegion *Reg = V.getAsRegion())
20906c3fb27SDimitry Andric     return getTaintedSymbolsImpl(State, Reg, Kind, returnFirstOnly);
21006c3fb27SDimitry Andric   return {};
21106c3fb27SDimitry Andric }
21206c3fb27SDimitry Andric 
21306c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
21406c3fb27SDimitry Andric                                                     const MemRegion *Reg,
21506c3fb27SDimitry Andric                                                     TaintTagType K,
21606c3fb27SDimitry Andric                                                     bool returnFirstOnly) {
21706c3fb27SDimitry Andric   std::vector<SymbolRef> TaintedSymbols;
21806c3fb27SDimitry Andric   if (!Reg)
21906c3fb27SDimitry Andric     return TaintedSymbols;
2205678d1d9SDimitry Andric 
2215678d1d9SDimitry Andric   // Element region (array element) is tainted if the offset is tainted.
22206c3fb27SDimitry Andric   if (const ElementRegion *ER = dyn_cast<ElementRegion>(Reg)) {
22306c3fb27SDimitry Andric     std::vector<SymbolRef> TaintedIndex =
22406c3fb27SDimitry Andric         getTaintedSymbolsImpl(State, ER->getIndex(), K, returnFirstOnly);
22506c3fb27SDimitry Andric     llvm::append_range(TaintedSymbols, TaintedIndex);
22606c3fb27SDimitry Andric     if (returnFirstOnly && !TaintedSymbols.empty())
22706c3fb27SDimitry Andric       return TaintedSymbols; // return early if needed
22806c3fb27SDimitry Andric   }
22906c3fb27SDimitry Andric 
2305678d1d9SDimitry Andric   // Symbolic region is tainted if the corresponding symbol is tainted.
23106c3fb27SDimitry Andric   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
23206c3fb27SDimitry Andric     std::vector<SymbolRef> TaintedRegions =
23306c3fb27SDimitry Andric         getTaintedSymbolsImpl(State, SR->getSymbol(), K, returnFirstOnly);
23406c3fb27SDimitry Andric     llvm::append_range(TaintedSymbols, TaintedRegions);
23506c3fb27SDimitry Andric     if (returnFirstOnly && !TaintedSymbols.empty())
23606c3fb27SDimitry Andric       return TaintedSymbols; // return early if needed
23706c3fb27SDimitry Andric   }
23806c3fb27SDimitry Andric 
2395678d1d9SDimitry Andric   // Any subregion (including Element and Symbolic regions) is tainted if its
2405678d1d9SDimitry Andric   // super-region is tainted.
24106c3fb27SDimitry Andric   if (const SubRegion *ER = dyn_cast<SubRegion>(Reg)) {
24206c3fb27SDimitry Andric     std::vector<SymbolRef> TaintedSubRegions =
24306c3fb27SDimitry Andric         getTaintedSymbolsImpl(State, ER->getSuperRegion(), K, returnFirstOnly);
24406c3fb27SDimitry Andric     llvm::append_range(TaintedSymbols, TaintedSubRegions);
24506c3fb27SDimitry Andric     if (returnFirstOnly && !TaintedSymbols.empty())
24606c3fb27SDimitry Andric       return TaintedSymbols; // return early if needed
24706c3fb27SDimitry Andric   }
24806c3fb27SDimitry Andric 
24906c3fb27SDimitry Andric   return TaintedSymbols;
25006c3fb27SDimitry Andric }
25106c3fb27SDimitry Andric 
25206c3fb27SDimitry Andric std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
25306c3fb27SDimitry Andric                                                     SymbolRef Sym,
25406c3fb27SDimitry Andric                                                     TaintTagType Kind,
25506c3fb27SDimitry Andric                                                     bool returnFirstOnly) {
25606c3fb27SDimitry Andric   std::vector<SymbolRef> TaintedSymbols;
25706c3fb27SDimitry Andric   if (!Sym)
25806c3fb27SDimitry Andric     return TaintedSymbols;
25906c3fb27SDimitry Andric 
260*6c4b055cSDimitry Andric   // HACK:https://discourse.llvm.org/t/rfc-make-istainted-and-complex-symbols-friends/79570
261*6c4b055cSDimitry Andric   if (const auto &Opts = State->getAnalysisManager().getAnalyzerOptions();
262*6c4b055cSDimitry Andric       Sym->computeComplexity() > Opts.MaxTaintedSymbolComplexity) {
263*6c4b055cSDimitry Andric     return {};
264*6c4b055cSDimitry Andric   }
265*6c4b055cSDimitry Andric 
26606c3fb27SDimitry Andric   // Traverse all the symbols this symbol depends on to see if any are tainted.
26706c3fb27SDimitry Andric   for (SymbolRef SubSym : Sym->symbols()) {
26806c3fb27SDimitry Andric     if (!isa<SymbolData>(SubSym))
26906c3fb27SDimitry Andric       continue;
27006c3fb27SDimitry Andric 
27106c3fb27SDimitry Andric     if (const TaintTagType *Tag = State->get<TaintMap>(SubSym)) {
27206c3fb27SDimitry Andric       if (*Tag == Kind) {
27306c3fb27SDimitry Andric         TaintedSymbols.push_back(SubSym);
27406c3fb27SDimitry Andric         if (returnFirstOnly)
27506c3fb27SDimitry Andric           return TaintedSymbols; // return early if needed
27606c3fb27SDimitry Andric       }
27706c3fb27SDimitry Andric     }
27806c3fb27SDimitry Andric 
27906c3fb27SDimitry Andric     if (const auto *SD = dyn_cast<SymbolDerived>(SubSym)) {
2800b57cec5SDimitry Andric       // If this is a SymbolDerived with a tainted parent, it's also tainted.
28106c3fb27SDimitry Andric       std::vector<SymbolRef> TaintedParents = getTaintedSymbolsImpl(
28206c3fb27SDimitry Andric           State, SD->getParentSymbol(), Kind, returnFirstOnly);
28306c3fb27SDimitry Andric       llvm::append_range(TaintedSymbols, TaintedParents);
28406c3fb27SDimitry Andric       if (returnFirstOnly && !TaintedSymbols.empty())
28506c3fb27SDimitry Andric         return TaintedSymbols; // return early if needed
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric       // If this is a SymbolDerived with the same parent symbol as another
28806c3fb27SDimitry Andric       // tainted SymbolDerived and a region that's a sub-region of that
28906c3fb27SDimitry Andric       // tainted symbol, it's also tainted.
2900b57cec5SDimitry Andric       if (const TaintedSubRegions *Regs =
2910b57cec5SDimitry Andric               State->get<DerivedSymTaint>(SD->getParentSymbol())) {
2920b57cec5SDimitry Andric         const TypedValueRegion *R = SD->getRegion();
2930b57cec5SDimitry Andric         for (auto I : *Regs) {
2940b57cec5SDimitry Andric           // FIXME: The logic to identify tainted regions could be more
2950b57cec5SDimitry Andric           // complete. For example, this would not currently identify
2960b57cec5SDimitry Andric           // overlapping fields in a union as tainted. To identify this we can
2970b57cec5SDimitry Andric           // check for overlapping/nested byte offsets.
29806c3fb27SDimitry Andric           if (Kind == I.second && R->isSubRegionOf(I.first)) {
29906c3fb27SDimitry Andric             TaintedSymbols.push_back(SD->getParentSymbol());
30006c3fb27SDimitry Andric             if (returnFirstOnly && !TaintedSymbols.empty())
30106c3fb27SDimitry Andric               return TaintedSymbols; // return early if needed
30206c3fb27SDimitry Andric           }
3030b57cec5SDimitry Andric         }
3040b57cec5SDimitry Andric       }
3050b57cec5SDimitry Andric     }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric     // If memory region is tainted, data is also tainted.
30806c3fb27SDimitry Andric     if (const auto *SRV = dyn_cast<SymbolRegionValue>(SubSym)) {
30906c3fb27SDimitry Andric       std::vector<SymbolRef> TaintedRegions =
31006c3fb27SDimitry Andric           getTaintedSymbolsImpl(State, SRV->getRegion(), Kind, returnFirstOnly);
31106c3fb27SDimitry Andric       llvm::append_range(TaintedSymbols, TaintedRegions);
31206c3fb27SDimitry Andric       if (returnFirstOnly && !TaintedSymbols.empty())
31306c3fb27SDimitry Andric         return TaintedSymbols; // return early if needed
3140b57cec5SDimitry Andric     }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric     // If this is a SymbolCast from a tainted value, it's also tainted.
31706c3fb27SDimitry Andric     if (const auto *SC = dyn_cast<SymbolCast>(SubSym)) {
31806c3fb27SDimitry Andric       std::vector<SymbolRef> TaintedCasts =
31906c3fb27SDimitry Andric           getTaintedSymbolsImpl(State, SC->getOperand(), Kind, returnFirstOnly);
32006c3fb27SDimitry Andric       llvm::append_range(TaintedSymbols, TaintedCasts);
32106c3fb27SDimitry Andric       if (returnFirstOnly && !TaintedSymbols.empty())
32206c3fb27SDimitry Andric         return TaintedSymbols; // return early if needed
3230b57cec5SDimitry Andric     }
3240b57cec5SDimitry Andric   }
32506c3fb27SDimitry Andric   return TaintedSymbols;
3260b57cec5SDimitry Andric }
327