@@ -378,10 +378,12 @@ struct GenericTaintRuleParser {
378378 CheckerManager &Mgr;
379379};
380380
381- class GenericTaintChecker : public Checker <check::PreCall, check::PostCall> {
381+ class GenericTaintChecker
382+ : public Checker<check::PreCall, check::PostCall, check::BeginFunction> {
382383public:
383384 void checkPreCall (const CallEvent &Call, CheckerContext &C) const ;
384385 void checkPostCall (const CallEvent &Call, CheckerContext &C) const ;
386+ void checkBeginFunction (CheckerContext &C) const ;
385387
386388 void printState (raw_ostream &Out, ProgramStateRef State, const char *NL,
387389 const char *Sep) const override ;
@@ -829,8 +831,94 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
829831 std::make_move_iterator (Rules.end ()));
830832}
831833
834+ bool isPointerToCharArray (const QualType &QT) {
835+ if (!QT->isPointerType ())
836+ return false ;
837+ QualType PointeeType = QT->getPointeeType ();
838+ return PointeeType->isPointerType () &&
839+ PointeeType->getPointeeType ()->isCharType ();
840+ }
841+
842+ // The incoming parameters of the main function get tainted
843+ // if the program called in an untrusted environment.
844+ void GenericTaintChecker::checkBeginFunction (CheckerContext &C) const {
845+ if (!C.inTopFrame () || C.getAnalysisManager ()
846+ .getAnalyzerOptions ()
847+ .ShouldAssumeControlledEnvironment )
848+ return ;
849+
850+ const auto *FD = dyn_cast<FunctionDecl>(C.getLocationContext ()->getDecl ());
851+ if (!FD || !FD->isMain () || FD->param_size () < 2 )
852+ return ;
853+
854+ if (!FD->parameters ()[0 ]->getType ()->isIntegerType ())
855+ return ;
856+
857+ if (!isPointerToCharArray (FD->parameters ()[1 ]->getType ()))
858+ return ;
859+ ProgramStateRef State = C.getState ();
860+
861+ const MemRegion *ArgcReg =
862+ State->getRegion (FD->parameters ()[0 ], C.getLocationContext ());
863+ SVal ArgcSVal = State->getSVal (ArgcReg);
864+ State = addTaint (State, ArgcSVal);
865+ StringRef ArgcName = FD->parameters ()[0 ]->getName ();
866+ if (auto N = ArgcSVal.getAs <NonLoc>()) {
867+ ConstraintManager &CM = C.getConstraintManager ();
868+ // The upper bound is the ARG_MAX on an arbitrary Linux
869+ // to model that is is typically smaller than INT_MAX.
870+ State = CM.assumeInclusiveRange (State, *N, llvm::APSInt::getUnsigned (1 ),
871+ llvm::APSInt::getUnsigned (2097152 ), true );
872+ }
873+
874+ const MemRegion *ArgvReg =
875+ State->getRegion (FD->parameters ()[1 ], C.getLocationContext ());
876+ SVal ArgvSVal = State->getSVal (ArgvReg);
877+ State = addTaint (State, ArgvSVal);
878+ StringRef ArgvName = FD->parameters ()[1 ]->getName ();
879+
880+ bool HaveEnvp = FD->param_size () > 2 ;
881+ SVal EnvpSVal;
882+ StringRef EnvpName;
883+ if (HaveEnvp && !isPointerToCharArray (FD->parameters ()[2 ]->getType ()))
884+ return ;
885+ if (HaveEnvp) {
886+ const MemRegion *EnvPReg =
887+ State->getRegion (FD->parameters ()[2 ], C.getLocationContext ());
888+ EnvpSVal = State->getSVal (EnvPReg);
889+ EnvpName = FD->parameters ()[2 ]->getName ();
890+ State = addTaint (State, EnvpSVal);
891+ }
892+
893+ const NoteTag *OriginatingTag =
894+ C.getNoteTag ([ArgvSVal, ArgcSVal, ArgcName, ArgvName, EnvpSVal,
895+ EnvpName](PathSensitiveBugReport &BR) -> std::string {
896+ if ((!BR.isInteresting (ArgcSVal) && !BR.isInteresting (ArgvSVal) &&
897+ !BR.isInteresting (EnvpSVal)))
898+ return " " ;
899+ if (BR.getBugType ().getCategory () != categories::TaintedData)
900+ return " " ;
901+ std::string Message = " " ;
902+ if (BR.isInteresting (ArgvSVal))
903+ Message += " '" + ArgvName.str () + " '" ;
904+ if (BR.isInteresting (ArgcSVal)) {
905+ if (Message.size () > 0 )
906+ Message += " , " ;
907+ Message += " '" + ArgcName.str () + " '" ;
908+ }
909+ if (BR.isInteresting (EnvpSVal)) {
910+ if (Message.size () > 0 )
911+ Message += " , " ;
912+ Message += " '" + EnvpName.str () + " '" ;
913+ }
914+ return " Taint originated in " + Message;
915+ });
916+ C.addTransition (State, OriginatingTag);
917+ }
918+
832919void GenericTaintChecker::checkPreCall (const CallEvent &Call,
833920 CheckerContext &C) const {
921+
834922 initTaintRules (C);
835923
836924 // FIXME: this should be much simpler.
0 commit comments