[clang] dfac905 - [clang][analyzer] Extend lifetime of dynamic extent information (#163562)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 17 02:59:13 PST 2025
Author: Balázs Kéri
Date: 2025-11-17T11:59:09+01:00
New Revision: dfac905925a66f7077d9ade3f2719f4fc9164aa3
URL: https://github.com/llvm/llvm-project/commit/dfac905925a66f7077d9ade3f2719f4fc9164aa3
DIFF: https://github.com/llvm/llvm-project/commit/dfac905925a66f7077d9ade3f2719f4fc9164aa3.diff
LOG: [clang][analyzer] Extend lifetime of dynamic extent information (#163562)
Symbols used for dynamic extent information of memory regions are now
kept as live as long as the memory region exists.
Added:
Modified:
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/test/Analysis/ArrayBound/verbose-tests.c
Removed:
################################################################################
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
index 1a9bef06b15a4..440603fb4d8c7 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
@@ -58,6 +58,8 @@ SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV);
DefinedOrUnknownSVal getDynamicElementCountWithOffset(ProgramStateRef State,
SVal BufV, QualType Ty);
+void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper);
+
} // namespace ento
} // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
index 34078dbce0b68..e5d5e0113eb2c 100644
--- a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -128,5 +128,12 @@ ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
}
+void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper) {
+ for (const auto &I : State->get<DynamicExtentMap>())
+ if (SymbolRef Sym = I.second.getAsSymbol())
+ if (SymReaper.isLiveRegion(I.first))
+ SymReaper.markLive(Sym);
+}
+
} // namespace ento
} // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 4e472b7fc38b0..a759aee47b8ea 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1079,6 +1079,11 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
DiagnosticStmt, *this, K);
+ // Extend lifetime of symbols used for dynamic extent while the parent region
+ // is live. In this way size information about memory allocations is not lost
+ // if the region remains live.
+ markAllDynamicExtentLive(CleanedState, SymReaper);
+
// For each node in CheckedSet, generate CleanedNodes that have the
// environment, the store, and the constraints cleaned up but have the
// user-supplied states as the predecessors.
diff --git a/clang/test/Analysis/ArrayBound/verbose-tests.c b/clang/test/Analysis/ArrayBound/verbose-tests.c
index e3416886d13e5..c0da93ea48591 100644
--- a/clang/test/Analysis/ArrayBound/verbose-tests.c
+++ b/clang/test/Analysis/ArrayBound/verbose-tests.c
@@ -381,30 +381,12 @@ int *symbolicExtent(int arg) {
return 0;
int *mem = (int*)malloc(arg);
- // TODO: without the following reference to 'arg', the analyzer would discard
- // the range information about (the symbolic value of) 'arg'. This is
- // incorrect because while the variable itself is inaccessible, it becomes
- // the symbolic extent of 'mem', so we still want to reason about its
- // potential values.
- (void)arg;
-
mem[8] = -2;
// expected-warning at -1 {{Out of bound access to memory after the end of the heap area}}
// expected-note at -2 {{Access of 'int' element in the heap area at index 8}}
return mem;
}
-int *symbolicExtentDiscardedRangeInfo(int arg) {
- // This is a copy of the case 'symbolicExtent' without the '(void)arg' hack.
- // TODO: if the analyzer can detect the out-of-bounds access within this
- // testcase, then remove this and the `(void)arg` hack from `symbolicExtent`.
- if (arg >= 5)
- return 0;
- int *mem = (int*)malloc(arg);
- mem[8] = -2;
- return mem;
-}
-
void symbolicIndex(int arg) {
// expected-note at +2 {{Assuming 'arg' is >= 12}}
// expected-note at +1 {{Taking true branch}}
@@ -426,9 +408,5 @@ int *nothingIsCertain(int x, int y) {
// {{Access of 'int' element in the heap area at an overflowing index}}
// but apparently the analyzer isn't smart enough to deduce this.
- // Keep constraints alive. (Without this, the overeager garbage collection of
- // constraints would _also_ prevent the intended behavior in this testcase.)
- (void)x;
-
return mem;
}
More information about the cfe-commits
mailing list