Example #1
0
// 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>
TaintReachable::process(const ContextID ctxt, const ImmutableCallSite cs) const {
  DEBUG(errs() << "Using taint reachable signature for: " << *cs.getInstruction() << "\n");

  FlowRecord exp(false,ctxt,ctxt);
  FlowRecord imp(true,ctxt,ctxt);

  // implicit from the pc of the call site and the function pointer
  imp.addSourceValue(*cs->getParent());
  imp.addSourceValue(*cs.getCalledValue());

  // Sources and sinks of the args
  for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end();
       arg != end; ++arg) {
      // every argument's value is a source
      exp.addSourceValue(**arg);
      // if the argument is a pointer, everything it reaches is a source
      // and everything it reaches is a sink
      if ((*arg)->getType()->isPointerTy()) {
	exp.addSourceReachablePtr(**arg);
	imp.addSourceValue(**arg);

	exp.addSinkReachablePtr(**arg);
	imp.addSinkReachablePtr(**arg);
      }
  }

  // if the function has a return value it is a sink
  if (!cs->getType()->isVoidTy()) {
    imp.addSinkValue(*cs.getInstruction());
    exp.addSinkValue(*cs.getInstruction());
  }

  std::vector<FlowRecord> flows;
  flows.push_back(imp);
  flows.push_back(exp);
  return flows;
}
void WinEHNumbering::processCallSite(ArrayRef<ActionHandler *> Actions,
                                     ImmutableCallSite CS) {
  int FirstMismatch = 0;
  for (int E = std::min(HandlerStack.size(), Actions.size()); FirstMismatch < E;
       ++FirstMismatch) {
    if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() !=
        Actions[FirstMismatch]->getHandlerBlockOrFunc())
      break;
    delete Actions[FirstMismatch];
  }

  bool EnteringScope = (int)Actions.size() > FirstMismatch;

  // Don't recurse while we are looping over the handler stack.  Instead, defer
  // the numbering of the catch handlers until we are done popping.
  SmallVector<CatchHandler *, 4> PoppedCatches;
  for (int I = HandlerStack.size() - 1; I >= FirstMismatch; --I) {
    if (auto *CH = dyn_cast<CatchHandler>(HandlerStack.back())) {
      PoppedCatches.push_back(CH);
    } else {
      // Delete cleanup handlers
      delete HandlerStack.back();
    }
    HandlerStack.pop_back();
  }

  // We need to create a new state number if we are exiting a try scope and we
  // will not push any more actions.
  int TryHigh = NextState - 1;
  if (!EnteringScope && !PoppedCatches.empty()) {
    createUnwindMapEntry(currentEHNumber(), nullptr);
    ++NextState;
  }

  int LastTryLowIdx = 0;
  for (int I = 0, E = PoppedCatches.size(); I != E; ++I) {
    CatchHandler *CH = PoppedCatches[I];
    if (I + 1 == E || CH->getEHState() != PoppedCatches[I + 1]->getEHState()) {
      int TryLow = CH->getEHState();
      auto Handlers =
          makeArrayRef(&PoppedCatches[LastTryLowIdx], I - LastTryLowIdx + 1);
      createTryBlockMapEntry(TryLow, TryHigh, Handlers);
      LastTryLowIdx = I + 1;
    }
  }

  for (CatchHandler *CH : PoppedCatches) {
    if (auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc()))
      calculateStateNumbers(*F);
    delete CH;
  }

  bool LastActionWasCatch = false;
  for (size_t I = FirstMismatch; I != Actions.size(); ++I) {
    // We can reuse eh states when pushing two catches for the same invoke.
    bool CurrActionIsCatch = isa<CatchHandler>(Actions[I]);
    // FIXME: Reenable this optimization!
    if (CurrActionIsCatch && LastActionWasCatch && false) {
      Actions[I]->setEHState(currentEHNumber());
    } else {
      createUnwindMapEntry(currentEHNumber(), Actions[I]);
      Actions[I]->setEHState(NextState);
      NextState++;
      DEBUG(dbgs() << "Creating unwind map entry for: (");
      print_name(Actions[I]->getHandlerBlockOrFunc());
      DEBUG(dbgs() << ", " << currentEHNumber() << ")\n");
    }
    HandlerStack.push_back(Actions[I]);
    LastActionWasCatch = CurrActionIsCatch;
  }

  DEBUG(dbgs() << "In EHState " << currentEHNumber() << " for CallSite: ");
  print_name(CS ? CS.getCalledValue() : nullptr);
  DEBUG(dbgs() << '\n');
}