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

Code before:
  if (!FD || !FD->isMain() || FD->param_size() < 2)
    return;

  ProgramStateRef State = C.getState();
  const MemRegion *ArgvReg =
      State->getRegion(FD->parameters()[1], C.getLocationContext());
  SVal ArgvSVal = State->getSVal(ArgvReg);
  State = addTaint(State, ArgvSVal);
  StringRef ArgvName = FD->parameters()[1]->getName();

  const MemRegion *ArgcReg =
      State->getRegion(FD->parameters()[0], C.getLocationContext());
  SVal ArgcSVal = State->getSVal(ArgcReg);
  State = addTaint(State, ArgcSVal);
  StringRef ArgcName = FD->parameters()[0]->getName();
  if (auto N = ArgcSVal.getAs<NonLoc>()) {
    ConstraintManager &CM = C.getConstraintManager();
    // The upper bound is the ARG_MAX on an arbitrary Linux
    // to model that is is typically smaller than INT_MAX.
    State = CM.assumeInclusiveRange(State, *N, llvm::APSInt::getUnsigned(1),
                                    llvm::APSInt::getUnsigned(2097152), true);
  }

  const NoteTag *OriginatingTag =
      C.getNoteTag([ArgvSVal, ArgcSVal, ArgcName,
                    ArgvName](PathSensitiveBugReport &BR) -> std::string {
        // We give diagnostics only for taint related reports
        if ((!BR.isInteresting(ArgcSVal) && !BR.isInteresting(ArgvSVal)) ||
            BR.getBugType().getCategory() != categories::TaintedData)
          return "";
        std::string Message = "Taint originated in ";
        if (BR.isInteresting(ArgvSVal) && BR.isInteresting(ArgcSVal))
          Message += "'" + ArgvName.str() + "' and '" + ArgcName.str() + "'";
        else if (BR.isInteresting(ArgvSVal))
          Message += "'" + ArgvName.str() + "'";
        else
          Message += "'" + ArgcName.str() + "'";
        return 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);

Review comment (suggestion):
We don't really check the types of the parameters. I think it would make sense to ensure that they are `int` for `argc` and for `argv` and `envp` it should be either `char**` or `char *[]` (without considering constness).

Code after:

// The incoming parameters of the main function get tainted
// if the program called in an untrusted environment.
void GenericTaintChecker::checkBeginFunction(CheckerContext &C) const {
  if (!C.inTopFrame() || C.getAnalysisManager()
                             .getAnalyzerOptions()
                             .ShouldAssumeControlledEnvironment)
    return;

  const auto *FD = dyn_cast<FunctionDecl>(C.getLocationContext()->getDecl());
  if (!FD || !FD->isMain() || FD->param_size() < 2)
    return;

  if (!FD->parameters()[0]->getType()->isIntegerType())
    return;

  if (!isPointerToCharArray(FD->parameters()[1]->getType()))
    return;
  ProgramStateRef State = C.getState();

  const MemRegion *ArgcReg =
      State->getRegion(FD->parameters()[0], C.getLocationContext());
  SVal ArgcSVal = State->getSVal(ArgcReg);
  State = addTaint(State, ArgcSVal);
  StringRef ArgcName = FD->parameters()[0]->getName();
  if (auto N = ArgcSVal.getAs<NonLoc>()) {
    ConstraintManager &CM = C.getConstraintManager();
    // The upper bound is the ARG_MAX on an arbitrary Linux
    // to model that is is typically smaller than INT_MAX.
    State = CM.assumeInclusiveRange(State, *N, llvm::APSInt::getUnsigned(1),
                                    llvm::APSInt::getUnsigned(2097152), true);
  }

  const MemRegion *ArgvReg =
      State->getRegion(FD->parameters()[1], C.getLocationContext());
  SVal ArgvSVal = State->getSVal(ArgvReg);
  State = addTaint(State, ArgvSVal);
  StringRef ArgvName = FD->parameters()[1]->getName();

  bool HaveEnvp = FD->param_size() > 2;
  SVal EnvpSVal;
  StringRef EnvpName;
  if (HaveEnvp && !isPointerToCharArray(FD->parameters()[2]->getType()))
    return;
  if (HaveEnvp) {
    const MemRegion *EnvPReg =
        State->getRegion(FD->parameters()[2], C.getLocationContext());
    EnvpSVal = State->getSVal(EnvPReg);
    EnvpName = FD->parameters()[2]->getName();
    State = addTaint(State, EnvpSVal);
  }