llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Benedek Kaibas (benedekaibas) <details> <summary>Changes</summary> If the same variable is dereferenced multiple times then the `DanglingPtrDeref` checker should only emit a single wanring for it instead of multiple ones. If there are multiple variables dereferenced then for each variable there should be one warning emitted. For that reason I have implemented the `markAsReported` function which returns the updated state with the memory region of the given variable marked as reported if the memory region is seen for the first time. --- Full diff: https://github.com/llvm/llvm-project/pull/215409.diff 4 Files Affected: - (modified) clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp (+6) - (modified) clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp (+8) - (modified) clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h (+5) - (modified) clang/test/Analysis/dangling-ptr-deref.cpp (+13) ``````````diff diff --git a/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp b/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp index bd4cd864cb768..cd690328ebc47 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp @@ -69,6 +69,11 @@ void DanglingPtrDeref::checkPostCall(const CallEvent &Call, void DanglingPtrDeref::reportUseAfterScope(const MemRegion *Region, const Stmt *S, ExplodedNode *N, CheckerContext &C) const { + ProgramStateRef ReportedState = + lifetime_modeling::markAsReported(N->getState(), Region); + if (!ReportedState) + return; + auto BR = std::make_unique<PathSensitiveBugReport>( BugMsg, (llvm::Twine("Use of ") + lifetime_modeling::getRegionName(Region) + @@ -79,6 +84,7 @@ void DanglingPtrDeref::reportUseAfterScope(const MemRegion *Region, if (const Expr *DerefExpr = bugreporter::getDerefExpr(S)) bugreporter::trackExpressionValue(N, DerefExpr, *BR); } + C.addTransition(ReportedState, N); C.emitReport(std::move(BR)); } diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp index 2fab20b199f01..d4a3cfd060aa3 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp @@ -15,6 +15,7 @@ REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(LifetimeSourceSet, const MemRegion *) REGISTER_MAP_WITH_PROGRAMSTATE(LifetimeBoundMap, SVal, LifetimeSourceSet) REGISTER_SET_WITH_PROGRAMSTATE(DeallocatedSourceSet, const MemRegion *) +REGISTER_SET_WITH_PROGRAMSTATE(ReportedDeadRegions, const MemRegion *) namespace { @@ -86,6 +87,13 @@ bool lifetime_modeling::isDeallocated(ProgramStateRef State, return State->contains<DeallocatedSourceSet>(Region->getBaseRegion()); } +ProgramStateRef lifetime_modeling::markAsReported(ProgramStateRef State, + const MemRegion *Region) { + if (State->contains<ReportedDeadRegions>(Region->getBaseRegion())) + return nullptr; + return State->add<ReportedDeadRegions>(Region->getBaseRegion()); +} + static ProgramStateRef bindSource(ProgramStateRef State, SVal RetVal, const MemRegion *Source) { LifetimeSourceSet::Factory &F = State->get_context<LifetimeSourceSet>(); diff --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h index 8d6c8e4882d1c..18f3014cfa6e9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h +++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.h @@ -22,6 +22,11 @@ bool isBoundToLifetimeSource(ProgramStateRef State, SVal Val); /// Returns the descriptive name of the memory region or a placeholder if a /// descriptive name cannot be constructed for it. std::string getRegionName(const MemRegion *Reg); + +/// Returns the updated \p State with \p R marked as reported if \p R is seen +/// the first time. Returns nullptr if \p R was already reported. +ProgramStateRef markAsReported(ProgramStateRef State, const MemRegion *Region); + } // namespace clang::ento::lifetime_modeling #endif // LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_LIFETIMEMODELING_H diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp b/clang/test/Analysis/dangling-ptr-deref.cpp index 7f13c241dadf0..58f4aa7fa7583 100644 --- a/clang/test/Analysis/dangling-ptr-deref.cpp +++ b/clang/test/Analysis/dangling-ptr-deref.cpp @@ -331,3 +331,16 @@ void dangling_through_calls() { // expected-warning@-1 {{Use of 'local' after its lifetime ended}} // expected-note@-2 {{Use of 'local' after its lifetime ended}} } + +// If the same variable is dereferenced multiple times then only +// report for the first dereference. +void multiple_deref() { + int *ptr = nullptr; + { + int a = 5; // expected-note {{'a' initialized to 5}} + ptr = &a; // expected-note {{Value assigned to 'ptr'}} + } // expected-note {{'a' is destroyed here}} + *ptr = 6; // expected-note {{Use of 'a' after its lifetime ended}} + // expected-warning@-1 {{Use of 'a' after its lifetime ended}} + *ptr = 7; +} `````````` </details> https://github.com/llvm/llvm-project/pull/215409 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
