================ @@ -718,6 +718,91 @@ class NoStateChangeFuncVisitor : public BugReporterVisitor { PathSensitiveBugReport &R) final; }; +/// Put a diagnostic on return statement of all inlined functions +/// for which the region of interest \p RegionOfInterest was passed into, +/// but not written inside, and it has caused an undefined read or a null +/// pointer dereference outside. +class NoStoreFuncVisitor final : public NoStateChangeFuncVisitor { + const SubRegion *RegionOfInterest; + MemRegionManager &MmrMgr; + const SourceManager &SM; + const PrintingPolicy &PP; + + /// Recursion limit for dereferencing fields when looking for the + /// region of interest. + /// The limit of two indicates that we will dereference fields only once. + static const unsigned DEREFERENCE_LIMIT = 2; + + using RegionVector = SmallVector<const MemRegion *, 5>; + +public: + NoStoreFuncVisitor( + const SubRegion *R, + bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough) + : NoStateChangeFuncVisitor(TKind), RegionOfInterest(R), + MmrMgr(R->getMemRegionManager()), + SM(MmrMgr.getContext().getSourceManager()), + PP(MmrMgr.getContext().getPrintingPolicy()) {} + + void Profile(llvm::FoldingSetNodeID &ID) const override { + static int Tag = 0; + ID.AddPointer(&Tag); + ID.AddPointer(RegionOfInterest); + } + +private: + /// \return Whether \c RegionOfInterest was modified at \p CurrN compared to + /// the value it holds in \p CallExitBeginN. + bool wasModifiedBeforeCallExit(const ExplodedNode *CurrN, + const ExplodedNode *CallExitBeginN) override; + + /// Attempts to find the region of interest in a given record decl, + /// by either following the base classes or fields. + /// Dereferences fields up to a given recursion limit. + /// Note that \p Vec is passed by value, leading to quadratic copying cost, + /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT. + /// \return A chain fields leading to the region of interest or std::nullopt. + const std::optional<RegionVector> + findRegionOfInterestInRecord(const RecordDecl *RD, ProgramStateRef State, + const MemRegion *R, const RegionVector &Vec = {}, + int depth = 0); + + // Region of interest corresponds to an IVar, exiting a method + // which could have written into that IVar, but did not. + PathDiagnosticPieceRef maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R, + const ObjCMethodCall &Call, + const ExplodedNode *N) final; + + PathDiagnosticPieceRef maybeEmitNoteForCXXThis(PathSensitiveBugReport &R, + const CXXConstructorCall &Call, + const ExplodedNode *N) final; + + PathDiagnosticPieceRef + maybeEmitNoteForParameters(PathSensitiveBugReport &R, const CallEvent &Call, + const ExplodedNode *N) final; + + /// Consume the information on the no-store stack frame in order to + /// either emit a note or suppress the report enirely. ---------------- NagyDonat wrote:
```suggestion /// either emit a note or suppress the report entirely. ``` Just a typo. https://github.com/llvm/llvm-project/pull/106982 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits