https://github.com/balazske updated https://github.com/llvm/llvm-project/pull/163562
From 8c8277f292ed2a908f72f012ac8d4ebe9a3312b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <[email protected]> Date: Fri, 10 Oct 2025 17:29:37 +0200 Subject: [PATCH 1/4] [clang][analyzer] Extend lifetime of dynamic extent information Symbols used for dynamic extent information of memory regions are now kept as live as long as the memory region exists. --- .../Core/PathSensitive/DynamicExtent.h | 2 ++ .../lib/StaticAnalyzer/Core/DynamicExtent.cpp | 6 ++++++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 ++ clang/test/Analysis/ArrayBound/verbose-tests.c | 18 ------------------ 4 files changed, 10 insertions(+), 18 deletions(-) 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..e436b186a2148 100644 --- a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp +++ b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp @@ -128,5 +128,11 @@ 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()) + SymReaper.markLive(Sym); +} + } // namespace ento } // namespace clang diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 785cdfa15bf04..d9ddc12c54985 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1064,6 +1064,8 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out, SymReaper.markLive(MR); } + markAllDynamicExtentLive(CleanedState, SymReaper); + getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper); // Create a state in which dead bindings are removed from the environment diff --git a/clang/test/Analysis/ArrayBound/verbose-tests.c b/clang/test/Analysis/ArrayBound/verbose-tests.c index e3416886d13e5..9ee290ab6b5b8 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@-1 {{Out of bound access to memory after the end of the heap area}} // expected-note@-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@+2 {{Assuming 'arg' is >= 12}} // expected-note@+1 {{Taking true branch}} From b7d9cc05efb1a69b2753b055843316499168617b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <[email protected]> Date: Mon, 20 Oct 2025 16:33:30 +0200 Subject: [PATCH 2/4] make symbol live only if region is live --- clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp | 3 ++- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp index e436b186a2148..e5d5e0113eb2c 100644 --- a/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp +++ b/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp @@ -131,7 +131,8 @@ ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper) { for (const auto &I : State->get<DynamicExtentMap>()) if (SymbolRef Sym = I.second.getAsSymbol()) - SymReaper.markLive(Sym); + if (SymReaper.isLiveRegion(I.first)) + SymReaper.markLive(Sym); } } // namespace ento diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index d9ddc12c54985..b116d9d39e160 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1064,8 +1064,6 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out, SymReaper.markLive(MR); } - markAllDynamicExtentLive(CleanedState, SymReaper); - getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper); // Create a state in which dead bindings are removed from the environment @@ -1081,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. From 03187735535465df7c9fb546ef38a298ba6413fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <[email protected]> Date: Fri, 31 Oct 2025 18:44:58 +0100 Subject: [PATCH 3/4] updated test comment --- clang/test/Analysis/ArrayBound/verbose-tests.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/test/Analysis/ArrayBound/verbose-tests.c b/clang/test/Analysis/ArrayBound/verbose-tests.c index 9ee290ab6b5b8..bc1915f734a25 100644 --- a/clang/test/Analysis/ArrayBound/verbose-tests.c +++ b/clang/test/Analysis/ArrayBound/verbose-tests.c @@ -408,8 +408,9 @@ 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.) + // Keep constraints alive. (Without this, it is possible that the overeager + // garbage collection of constraints _also_ prevents the intended behavior in + // this testcase.) (void)x; return mem; From 946fe1a3b5d655090d4920a7f6221eef4f482456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <[email protected]> Date: Mon, 10 Nov 2025 17:38:18 +0100 Subject: [PATCH 4/4] cleanup of test --- clang/test/Analysis/ArrayBound/verbose-tests.c | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/test/Analysis/ArrayBound/verbose-tests.c b/clang/test/Analysis/ArrayBound/verbose-tests.c index bc1915f734a25..fd17010daf71f 100644 --- a/clang/test/Analysis/ArrayBound/verbose-tests.c +++ b/clang/test/Analysis/ArrayBound/verbose-tests.c @@ -411,7 +411,6 @@ int *nothingIsCertain(int x, int y) { // Keep constraints alive. (Without this, it is possible that the overeager // garbage collection of constraints _also_ prevents the intended behavior in // this testcase.) - (void)x; return mem; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
