Author: Balázs Benics
Date: 2025-11-24T09:30:11Z
New Revision: 30b1d1422733c012c274f173a3f4986615f7c1c7

URL: 
https://github.com/llvm/llvm-project/commit/30b1d1422733c012c274f173a3f4986615f7c1c7
DIFF: 
https://github.com/llvm/llvm-project/commit/30b1d1422733c012c274f173a3f4986615f7c1c7.diff

LOG: [analyzer] Fix inf recursion in StackAddrEscapeChecker for self 
referencing blocks (#169208)

Objective-C blocks are like lambdas. They have captures, just like lambdas.
However, they can also implicitly capture themselves unlike lambdas.

This means that when walking the captures of a block, we may end up in
infinite recursion. This is not possible with lambdas, but happened in
practice with blocks downstream.

In this patch, I just use a set to keep track of the visited MemRegions.

Note that theoretically, there is nothing preventing usual lambdas or
functors from falling for the same trap, but probably slightly more
difficult to do so. You would likely need a pointer to itself, etc. I'll
not speculate here.

This inf recursion was likely caused by #126620, released in clang-21.

rdar://162215172

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
    clang/test/Analysis/stackaddrleak.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 019e81f91400d..027bf780273cc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -22,6 +22,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 using namespace ento;
@@ -247,6 +248,7 @@ class FindStackRegionsSymbolVisitor final : public 
SymbolVisitor {
   CheckerContext &Ctxt;
   const StackFrameContext *PoppedStackFrame;
   SmallVectorImpl<const MemRegion *> &EscapingStackRegions;
+  llvm::SmallPtrSet<const MemRegion *, 16> VisitedRegions;
 
 public:
   explicit FindStackRegionsSymbolVisitor(
@@ -258,6 +260,9 @@ class FindStackRegionsSymbolVisitor final : public 
SymbolVisitor {
   bool VisitSymbol(SymbolRef sym) override { return true; }
 
   bool VisitMemRegion(const MemRegion *MR) override {
+    if (!VisitedRegions.insert(MR).second)
+      return true;
+
     SaveIfEscapes(MR);
 
     if (const BlockDataRegion *BDR = MR->getAs<BlockDataRegion>())

diff  --git a/clang/test/Analysis/stackaddrleak.c 
b/clang/test/Analysis/stackaddrleak.c
index 95175996e8274..96bd4e4ea19e5 100644
--- a/clang/test/Analysis/stackaddrleak.c
+++ b/clang/test/Analysis/stackaddrleak.c
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -std=c99 
-Dbool=_Bool -Wno-bool-conversion %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -x c++ 
-Wno-bool-conversion %s
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -verify 
-std=c99 -Dbool=_Bool -Wno-bool-conversion %s
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc -verify 
-x c++ -Wno-bool-conversion %s
 
 typedef __INTPTR_TYPE__ intptr_t;
 char const *p;
@@ -90,3 +90,14 @@ struct child_stack_context_s 
return_child_stack_context_field() {
   }
   return s; // expected-warning {{Address of stack memory associated with 
local variable 'a' returned to caller}}
 }
+
+// Returns an 'int' block taking an 'int'.
+int (^copy_self_referencing_block(void))(int) {
+  // It is important that the 'fib' block captures itself.
+  __block int (^fib)(int) = ^(int n) {
+    if (n <= 1) return n;
+    return fib(n - 1) + fib(n - 2);
+  };
+  return fib; // no-crash when copying a self-referencing 'fib'
+  // expected-warning-re@-1 {{Address of stack-allocated block declared on 
line {{[0-9]+}} is captured by a returned block}}
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to