[clang] 252f31a - [analyzer] Detect dangling pointers passed to function calls (#211045)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 22 13:48:37 PDT 2026
Author: Benedek Kaibas
Date: 2026-07-22T22:48:32+02:00
New Revision: 252f31a6893b6a3dcb8b2a404e13933e376bf36b
URL: https://github.com/llvm/llvm-project/commit/252f31a6893b6a3dcb8b2a404e13933e376bf36b
DIFF: https://github.com/llvm/llvm-project/commit/252f31a6893b6a3dcb8b2a404e13933e376bf36b.diff
LOG: [analyzer] Detect dangling pointers passed to function calls (#211045)
In order to detect if a dangling pointer is passed to a function the
analyzer has to inspect each call argument. For that reason I have
implemented the `checkPostCall` for the `DanglingPtrDeref` checker to
check if an argument passed to a function is dangling. Since
`checkLocation` only catches dereferences and cannot reason about
whether an argument passed to a function is dangling it cannot detect
these type of bugs alone.
Added:
Modified:
clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp
clang/test/Analysis/dangling-ptr-deref.cpp
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp b/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp
index 781045a4d0654..ff2087e1db933 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DanglingPtrDeref.cpp
@@ -3,16 +3,18 @@
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
using namespace clang;
using namespace ento;
namespace {
-class DanglingPtrDeref : public Checker<check::Location> {
+class DanglingPtrDeref : public Checker<check::Location, check::PostCall> {
public:
void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
CheckerContext &C) const;
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N,
CheckerContext &C) const;
const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
@@ -48,6 +50,22 @@ void DanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
}
}
+void DanglingPtrDeref::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ // Only check calls arguments if it is not inlined by the engine. In case a
+ // function is inlined checkLocation handles any dereference in its body.
+ if (C.wasInlined)
+ return;
+
+ for (unsigned Idx = 0; Idx < Call.getNumArgs(); Idx++) {
+ if (const MemRegion *ArgRegion = Call.getArgSVal(Idx).getAsRegion())
+ if (lifetime_modeling::isDeallocated(State, ArgRegion))
+ if (ExplodedNode *N = C.generateNonFatalErrorNode())
+ reportUseAfterScope(ArgRegion, N, C);
+ }
+}
+
void DanglingPtrDeref::reportUseAfterScope(const MemRegion *Region,
ExplodedNode *N,
CheckerContext &C) const {
diff --git a/clang/test/Analysis/dangling-ptr-deref.cpp b/clang/test/Analysis/dangling-ptr-deref.cpp
index ad6a9aceb5981..e661eff9ccbb6 100644
--- a/clang/test/Analysis/dangling-ptr-deref.cpp
+++ b/clang/test/Analysis/dangling-ptr-deref.cpp
@@ -84,3 +84,31 @@ void test_case_seven() {
// expected-warning at -1 {{Use of 'i' after its lifetime ended}}
// expected-note at -2 {{Use of 'i' after its lifetime ended}}
}
+
+void passing_dangling_ptr_to_opaque_func() {
+ int *ptr = nullptr;
+ {
+ int num = 5;
+ ptr = #
+ }
+ // expected-note at -1 {{'num' is destroyed here}}
+ escape(ptr);
+ // expected-warning at -1 {{Use of 'num' after its lifetime ended}}
+ // expected-note at -2 {{Use of 'num' after its lifetime ended}}
+}
+
+int deref_param(int *p) { return *p; }
+// expected-warning at -1 {{Use of 'num' after its lifetime ended}}
+// expected-note at -2 {{Use of 'num' after its lifetime ended}}
+
+void inlined_callee_single_report() {
+ int *ptr = nullptr;
+ {
+ int num = 5;
+ ptr = #
+ }
+ // expected-note at -1 {{'num' is destroyed here}}
+ int r = deref_param(ptr);
+ // expected-note at -1 {{Calling 'deref_param'}}
+ (void)r;
+}
More information about the cfe-commits
mailing list