// Helper to find the set of values described by a TSpecifier std::set<const Value*> getValues(const ImmutableCallSite cs, TSpecifier TS) { std::set<const Value*> Values; switch (TS) { case Ret: assert(!cs.getInstruction()->getType()->isVoidTy()); Values.insert(cs.getInstruction()); break; case Arg0: assert(0 < cs.arg_size()); Values.insert(cs.getArgument(0)); break; case Arg1: assert(1 < cs.arg_size()); Values.insert(cs.getArgument(1)); break; case Arg2: assert(2 < cs.arg_size()); Values.insert(cs.getArgument(2)); break; case Arg3: assert(3 < cs.arg_size()); Values.insert(cs.getArgument(3)); break; case Arg4: assert(4 < cs.arg_size()); Values.insert(cs.getArgument(4)); break; case AllArgs: assert(!cs.arg_empty()); for (unsigned i = 0; i < cs.arg_size(); ++i) Values.insert(cs.getArgument(i)); break; case VarArgs: { const Value *Callee = cs.getCalledValue()->stripPointerCasts(); FunctionType *CalleeType = dyn_cast<FunctionType>( dyn_cast<PointerType>(Callee->getType())->getElementType() ); for (unsigned i = CalleeType->getNumParams(); i < cs.arg_size(); ++i) Values.insert(cs.getArgument(i)); break; } } return Values; }
std::vector<FlowRecord> StdLib::process(const ContextID ctxt, const ImmutableCallSite cs) const { const CallSummary *S; bool found = findEntry(cs, S); assert(found); std::vector<FlowRecord> flows; // If there are no flows for this call, return empty vector // Similarly if the call has no arguments we already know // it has no sources so just return empty vector. if (S->Sources.empty() || cs.arg_empty()) { return flows; } // Otherwise, build up a flow record for this summary FlowRecord flow(ctxt, ctxt); // First, process all sources for (std::vector<TaintDecl>::const_iterator I = S->Sources.begin(), E = S->Sources.end(); I != E; ++I) { const TaintDecl & TD = *I; assert(TD.end == T_Source); std::set<const Value*> Values = getValues(cs, TD.which); switch (TD.what) { case V: // Value flow.addSourceValue(Values.begin(), Values.end()); break; case D: // DirectPtr flow.addSourceDirectPtr(Values.begin(), Values.end()); break; case R: // Reachable flow.addSourceReachablePtr(Values.begin(), Values.end()); break; } } // Then add all sinks for (std::vector<TaintDecl>::const_iterator I = S->Sinks.begin(), E = S->Sinks.end(); I != E; ++I) { const TaintDecl & TD = *I; assert(TD.end == T_Sink); std::set<const Value*> Values = getValues(cs, TD.which); switch (TD.what) { case V: // Value flow.addSinkValue(Values.begin(), Values.end()); break; case D: // DirectPtr flow.addSinkDirectPtr(Values.begin(), Values.end()); break; case R: // Reachable flow.addSinkReachablePtr(Values.begin(), Values.end()); break; } } // Finally, stash it in the vector and return flows.push_back(flow); return flows; }