llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Peiqi Li (voyager-jhk)

<details>
<summary>Changes</summary>

Pointers stored in heap fields are incorrectly considered escaped, causing 
leaks to go unreported.

Fixes #<!-- -->214226

---
Full diff: https://github.com/llvm/llvm-project/pull/221587.diff


3 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+4-2) 
- (modified) clang/test/Analysis/NewDeleteLeaks.cpp (+23) 
- (modified) clang/test/Analysis/malloc.c (+8-1) 


``````````diff
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index f0f7d78fc5d50..69b091650c9f5 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3442,7 +3442,8 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, 
ExplodedNode *Pred,
 
 // A value escapes in four possible cases:
 // (1) We are binding to something that is not a memory region.
-// (2) We are binding to a MemRegion that does not have stack storage.
+// (2) We are binding to a MemRegion that is not in stack, static-local,
+//     or heap space.
 // (3) We are binding to a top-level parameter region with a non-trivial
 //     destructor. We won't see the destructor during analysis, but it's there.
 // (4) We are binding to a MemRegion with stack storage that the store
@@ -3455,7 +3456,8 @@ ProgramStateRef ExprEngine::processPointerEscapedOnBind(
     // Cases (1) and (2).
     const MemRegion *MR = LocAndVal.first.getAsRegion();
     const MemSpaceRegion *Space = MR ? MR->getMemorySpace(State) : nullptr;
-    if (!MR || !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(Space)) {
+    if (!MR || !isa<StackSpaceRegion, StaticGlobalSpaceRegion, 
HeapSpaceRegion>(
+                   Space)) {
       Escaped.push_back(LocAndVal.second);
       continue;
     }
diff --git a/clang/test/Analysis/NewDeleteLeaks.cpp 
b/clang/test/Analysis/NewDeleteLeaks.cpp
index d9c4b77d1e6fc..e133a653873c7 100644
--- a/clang/test/Analysis/NewDeleteLeaks.cpp
+++ b/clang/test/Analysis/NewDeleteLeaks.cpp
@@ -251,3 +251,26 @@ void validate_system_header() {
 }
 
 } // namespace protobuf_leak
+
+// GH214226: Do not treat pointers stored in heap fields as escaped.
+namespace heap_field_bind {
+
+struct Owner {
+  int *member;
+  Owner() : member(new int(42)) {} // expected-note {{Memory is allocated}}
+};
+
+void leak_member_when_owner_deleted() {
+  Owner *owner = new Owner; // expected-note {{Calling default constructor for 
'Owner'}}
+                            // expected-note@-1 {{Returning from default 
constructor for 'Owner'}}
+  delete owner;
+} // expected-warning {{Potential leak of memory pointed to by field 'member'}}
+// expected-note@-1 {{Potential leak of memory pointed to by field 'member'}}
+
+void member_released_before_owner() {
+  Owner *owner = new Owner;
+  delete owner->member;
+  delete owner;
+} // no-warning
+
+} // namespace heap_field_bind
diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c
index 6c3dadfd16021..0e8a84447c952 100644
--- a/clang/test/Analysis/malloc.c
+++ b/clang/test/Analysis/malloc.c
@@ -1771,7 +1771,14 @@ void testMallocIntoMalloc(void) {
   StructWithPtr *s = malloc(sizeof(StructWithPtr));
   s->memP = malloc(sizeof(int));
   free(s);
-} // FIXME: should warn here
+} // expected-warning {{Potential leak of memory pointed to by field 'memP'}}
+
+void testMallocIntoMallocThenFreeMember(void) {
+  StructWithPtr *s = malloc(sizeof(StructWithPtr));
+  s->memP = malloc(sizeof(int));
+  free(s->memP);
+  free(s);
+} // no-warning
 
 int conjure(void);
 void testExtent(void) {

``````````

</details>


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

Reply via email to