From 8f40afbf7740c39fccaa4b8cc5aa2814d5ed6fdc Mon Sep 17 00:00:00 2001
From: Ted Kremenek <kremenek@apple.com>
Date: Thu, 26 Apr 2012 05:08:26 +0000
Subject: [PATCH] [analyzer] check lazy bindings in RegionStore first before
 looking for default values.  Fixes <rdar://problem/11269741>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155615 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/StaticAnalyzer/Core/RegionStore.cpp | 16 ++++++++--------
 test/Analysis/malloc.c                  | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index cc3ea8c3bf5..e849333f94e 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1274,7 +1274,15 @@ SVal RegionStoreManager::getBindingForFieldOrElementCommon(Store store,
   // At this point we have already checked in either getBindingForElement or
   // getBindingForField if 'R' has a direct binding.
   RegionBindings B = GetRegionBindings(store);
+
+  // Lazy binding?
+  Store lazyBindingStore = NULL;
+  const MemRegion *lazyBindingRegion = NULL;
+  llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R, R);
   
+  if (lazyBindingRegion)
+    return getLazyBinding(lazyBindingRegion, lazyBindingStore);
+
   // Record whether or not we see a symbolic index.  That can completely
   // be out of scope of our lookup.
   bool hasSymbolicIndex = false;
@@ -1299,14 +1307,6 @@ SVal RegionStoreManager::getBindingForFieldOrElementCommon(Store store,
     break;
   }
 
-  // Lazy binding?
-  Store lazyBindingStore = NULL;
-  const MemRegion *lazyBindingRegion = NULL;
-  llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R, R);
-
-  if (lazyBindingRegion)
-    return getLazyBinding(lazyBindingRegion, lazyBindingStore);
-
   if (R->hasStackNonParametersStorage()) {
     if (isa<ElementRegion>(R)) {
       // Currently we don't reason specially about Clang-style vectors.  Check
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index 3b4712320b7..32c6171f8c4 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -760,6 +760,22 @@ void radar10978247_positive(int myValueSize) {
     return;
 }
 
+// <rdar://problem/11269741> Previously this triggered a false positive
+// because malloc() is known to return uninitialized memory and the binding
+// of 'o' to 'p->n' was not getting propertly handled.  Now we report a leak.
+struct rdar11269741_a_t {
+  struct rdar11269741_b_t {
+    int m;
+  } n;
+};
+
+int rdar11269741(struct rdar11269741_b_t o)
+{
+  struct rdar11269741_a_t *p = (struct rdar11269741_a_t *) malloc(sizeof(*p));
+  p->n = o;
+  return p->n.m; // expected-warning {{leak}}
+}
+
 // ----------------------------------------------------------------------------
 // Below are the known false positives.
 
-- 
GitLab