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