Repository: llvm/llvm-project
File: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp (C++)

Code before:
    State = addTaint(State, EnvpSVal);
  }

  const NoteTag *OriginatingTag =
      C.getNoteTag([ArgvSVal, ArgcSVal, ArgcName, ArgvName, EnvpSVal,
                    EnvpName](PathSensitiveBugReport &BR) -> std::string {
        // We give diagnostics only for taint related reports
        if ((!BR.isInteresting(ArgcSVal) && !BR.isInteresting(ArgvSVal) &&
             !BR.isInteresting(EnvpSVal)) ||
            BR.getBugType().getCategory() != categories::TaintedData)
          return "";
        std::string Message = "";
        if (BR.isInteresting(ArgvSVal))
          Message += "'" + ArgvName.str() + "'";
        if (BR.isInteresting(ArgcSVal)) {
          if (Message.size() > 0)
            Message += ", ";
          Message += "'" + ArgcName.str() + "'";
        }
        if (BR.isInteresting(EnvpSVal)) {
          if (Message.size() > 0)
            Message += ", ";
          Message += "'" + EnvpName.str() + "'";
        }
        return "Taint originated in " + Message;
      });
  C.addTransition(State, OriginatingTag);
}

void GenericTaintChecker::checkPreCall(const CallEvent &Call,
                                       CheckerContext &C) const {

  initTaintRules(C);

  // FIXME: this should be much simpler.
  if (const auto *Rule =
          Call.isGlobalCFunction() ? StaticTaintRules->lookup(Call) : nullptr)
    Rule->process(*this, Call, C);
  else if (const auto *Rule = DynamicTaintRules->lookup(Call))
    Rule->process(*this, Call, C);

  // FIXME: These edge cases are to be eliminated from here eventually.
  //
  // Additional check that is not supported by CallDescription.
  // TODO: Make CallDescription be able to match attributes such as printf-like
  // arguments.
  checkUncontrolledFormatString(Call, C);

  // TODO: Modeling sockets should be done in a specific checker.
  // Socket is a source, which taints the return value.
  taintUnsafeSocketProtocol(Call, C);

Review comment (bug):
```suggestion
  const NoteTag *OriginatingTag =
      C.getNoteTag([ArgvSVal, ArgcSVal, ArgcName, ArgvName, EnvpSVal,
                    EnvpName](PathSensitiveBugReport &BR) -> std::string {
        if (BR.getBugType().getCategory() != categories::TaintedData)
          return "";

        std::string Message;
        llvm::raw_string_ostream OS(Message);

        auto Quote = [&](StringRef X) { OS << "'" << X << "'"; };
        auto First = [](const auto &Pair) { return std::get<0>(Pair); };
        auto Second = [](const auto &Pair) { return std::get<1>(Pair); };
        auto isArgInteresting = [&](const auto &Pair) {
          return BR.isInteresting(First(Pair));
        };

        auto ArgSVals = {ArgvSVal, ArgcSVal, EnvpSVal};
        auto ArgNames = {ArgvName, ArgcName, EnvpName};
        auto Pairs = llvm::zip_equal(ArgSVals, ArgNames);
        auto InterestingNames = llvm::to_vector(llvm::map_range(
            llvm::make_filter_range(Pairs, isArgInteresting), Second));
        if (InterestingNames.empty())
          return "";

        OS << "Taint originated in ";
        llvm::interleaveComma(InterestingNames, OS, Quote);
        return Message;
      });
```

Code after:
    State = addTaint(State, EnvpSVal);
  }

  const NoteTag *OriginatingTag =
      C.getNoteTag([ArgvSVal, ArgcSVal, ArgcName, ArgvName, EnvpSVal,
                    EnvpName](PathSensitiveBugReport &BR) -> std::string {
        if ((!BR.isInteresting(ArgcSVal) && !BR.isInteresting(ArgvSVal) &&
             !BR.isInteresting(EnvpSVal)))
          return "";
        if (BR.getBugType().getCategory() != categories::TaintedData)
          return "";
        std::string Message = "";
        if (BR.isInteresting(ArgvSVal))
          Message += "'" + ArgvName.str() + "'";
        if (BR.isInteresting(ArgcSVal)) {
          if (Message.size() > 0)
            Message += ", ";
          Message += "'" + ArgcName.str() + "'";
        }
        if (BR.isInteresting(EnvpSVal)) {
          if (Message.size() > 0)
            Message += ", ";
          Message += "'" + EnvpName.str() + "'";
        }
        return "Taint originated in " + Message;
      });
  C.addTransition(State, OriginatingTag);
}

void GenericTaintChecker::checkPreCall(const CallEvent &Call,
                                       CheckerContext &C) const {

  initTaintRules(C);

  // FIXME: this should be much simpler.
  if (const auto *Rule =
          Call.isGlobalCFunction() ? StaticTaintRules->lookup(Call) : nullptr)
    Rule->process(*this, Call, C);
  else if (const auto *Rule = DynamicTaintRules->lookup(Call))
    Rule->process(*this, Call, C);

  // FIXME: These edge cases are to be eliminated from here eventually.
  //
  // Additional check that is not supported by CallDescription.
  // TODO: Make CallDescription be able to match attributes such as printf-like
  // arguments.
  checkUncontrolledFormatString(Call, C);

  // TODO: Modeling sockets should be done in a specific checker.
  // Socket is a source, which taints the return value.
  taintUnsafeSocketProtocol(Call, C);