diff options
author | DonĂ¡t Nagy <donat.nagy@ericsson.com> | 2025-07-24 16:18:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-24 16:18:37 +0200 |
commit | deede2b2db262a932f07a386e59c2ca0b1a798d1 (patch) | |
tree | de78580c6aa5512143e0fc448e0070aa6f748fa2 /clang/lib/StaticAnalyzer | |
parent | 0c4d56a6747b0f9677b47cba82053ac92ba67962 (diff) | |
download | llvm-deede2b2db262a932f07a386e59c2ca0b1a798d1.zip llvm-deede2b2db262a932f07a386e59c2ca0b1a798d1.tar.gz llvm-deede2b2db262a932f07a386e59c2ca0b1a798d1.tar.bz2 |
[analyzer] Eliminate unique release point assertion (#150240)
MallocChecker.cpp has a complex heuristic that supresses reports where
the memory release happens during the release of a reference-counted
object (to suppress a significant amount of false positives).
Previously this logic asserted that there is at most one release point
corresponding to a symbol, but it turns out that there is a rare corner
case where the symbol can be released, forgotten and then released
again. This commit removes that assertion to avoid the crash. (As this
issue just affects a bug suppression heuristic, I didn't want to dig
deeper and modify the way the state of the symbol is changed.)
Fixes #149754
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 68efdba..a7704da 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -3730,13 +3730,15 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N, return nullptr; } - // Save the first destructor/function as release point. - assert(!ReleaseFunctionLC && "There should be only one release point"); + // Record the stack frame that is _responsible_ for this memory release + // event. This will be used by the false positive suppression heuristics + // that recognize the release points of reference-counted objects. + // + // Usually (e.g. in C) we say that the _responsible_ stack frame is the + // current innermost stack frame: ReleaseFunctionLC = CurrentLC->getStackFrame(); - - // See if we're releasing memory while inlining a destructor that - // decrement reference counters (or one of its callees). - // This turns on various common false positive suppressions. + // ...but if the stack contains a destructor call, then we say that the + // outermost destructor stack frame is the _responsible_ one: for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) { if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) { if (isReferenceCountingPointerDestructor(DD)) { |