Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 7 additions & 0 deletions clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,12 @@ ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
}

void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper) {
Copy link
Contributor

@NagyDonat NagyDonat Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps rename this to transferLivenessToDynamicExtent or something similar now that we no longer mark all the dynamic extent values as live?

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
5 changes: 5 additions & 0 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 0 additions & 18 deletions clang/test/Analysis/ArrayBound/verbose-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
Loading