]> granicus.if.org Git - clang/commitdiff
static analyzer: Fix use-after-free bug in RegionStore involving LazyCompoundValueDat...
authorTed Kremenek <kremenek@apple.com>
Tue, 8 Mar 2011 23:18:00 +0000 (23:18 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 8 Mar 2011 23:18:00 +0000 (23:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127288 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h [new file with mode: 0644]
lib/StaticAnalyzer/Core/BasicValueFactory.cpp
lib/StaticAnalyzer/Core/RegionStore.cpp
test/Analysis/misc-ps-region-store.m

index a4327e127f5fed2cf6506da0ca37d9ebc8f29752..65fbfcc912f92f6d3eca1fc7f6c059c9cfc8581d 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H
 #define LLVM_CLANG_GR_BASICVALUEFACTORY_H
 
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/AST/ASTContext.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -47,16 +48,17 @@ public:
 };
 
 class LazyCompoundValData : public llvm::FoldingSetNode {
-  const void *store;
+  StoreRef store;
   const TypedRegion *region;
 public:
-  LazyCompoundValData(const void *st, const TypedRegion *r)
+  LazyCompoundValData(const StoreRef &st, const TypedRegion *r)
     : store(st), region(r) {}
 
-  const void *getStore() const { return store; }
+  const void *getStore() const { return store.getStore(); }
   const TypedRegion *getRegion() const { return region; }
 
-  static void Profile(llvm::FoldingSetNodeID& ID, const void *store,
+  static void Profile(llvm::FoldingSetNodeID& ID,
+                      const StoreRef &store,
                       const TypedRegion *region);
 
   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
@@ -170,7 +172,7 @@ public:
   const CompoundValData *getCompoundValData(QualType T,
                                             llvm::ImmutableList<SVal> Vals);
 
-  const LazyCompoundValData *getLazyCompoundValData(const void *store,
+  const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store,
                                                     const TypedRegion *region);
 
   llvm::ImmutableList<SVal> getEmptySValList() {
index 4b08f2064014cb85dc9111acd7b19563645b3453..0f9e56aa2ff8887a70a4689c04a1ef0e317a597a 100644 (file)
@@ -154,7 +154,7 @@ public:
     return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals));
   }
 
-  NonLoc makeLazyCompoundVal(const void *store, const TypedRegion *region) {
+  NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedRegion *region) {
     return nonloc::LazyCompoundVal(
         BasicVals.getLazyCompoundValData(store, region));
   }
index 0251311c27ae459e0bae77d3eb0b7c3065637705..21c6ae760cc8d7acd292c3617b1bf8ae1597738b 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_GR_STORE_H
 #define LLVM_CLANG_GR_STORE_H
 
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
 #include "llvm/ADT/DenseSet.h"
@@ -28,36 +29,10 @@ class StackFrameContext;
 
 namespace ento {
 
-/// Store - This opaque type encapsulates an immutable mapping from
-///  locations to values.  At a high-level, it represents the symbolic
-///  memory model.  Different subclasses of StoreManager may choose
-///  different types to represent the locations and values.
-typedef const void* Store;
-
 class GRState;
 class GRStateManager;
 class SubRegionMap;
-class StoreManager;
-  
-class StoreRef {
-  Store store;
-  StoreManager &mgr;
-public:
-  StoreRef(Store, StoreManager &);
-  StoreRef(const StoreRef &);
-  StoreRef &operator=(StoreRef const &);
-  
-  bool operator==(const StoreRef &x) const {
-    assert(&mgr == &x.mgr);
-    return x.store == store;
-  }
-  bool operator!=(const StoreRef &x) const { return !operator==(x); }
 
-  ~StoreRef();
-  
-  Store getStore() const { return store; }
-};
-  
 class StoreManager {
 protected:
   SValBuilder &svalBuilder;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
new file mode 100644 (file)
index 0000000..0662ead
--- /dev/null
@@ -0,0 +1,50 @@
+//== StoreRef.h - Smart pointer for store objects ---------------*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defined the type StoreRef.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_STOREREF_H
+#define LLVM_CLANG_GR_STOREREF_H
+
+#include <cassert>
+
+namespace clang {
+namespace ento {
+  
+/// Store - This opaque type encapsulates an immutable mapping from
+///  locations to values.  At a high-level, it represents the symbolic
+///  memory model.  Different subclasses of StoreManager may choose
+///  different types to represent the locations and values.
+typedef const void* Store;
+  
+class StoreManager;
+  
+class StoreRef {
+  Store store;
+  StoreManager &mgr;
+public:
+  StoreRef(Store, StoreManager &);
+  StoreRef(const StoreRef &);
+  StoreRef &operator=(StoreRef const &);
+  
+  bool operator==(const StoreRef &x) const {
+    assert(&mgr == &x.mgr);
+    return x.store == store;
+  }
+  bool operator!=(const StoreRef &x) const { return !operator==(x); }
+  
+  ~StoreRef();
+  
+  Store getStore() const { return store; }
+};
+
+}}
+#endif
index 6315d83d894dde8e2278ebb0ad99effc3e4b836d..d29c86adcfafe63f7209e7b6c663e5db2c1d2c23 100644 (file)
@@ -25,8 +25,9 @@ void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
 }
 
 void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
-                                  const void *store,const TypedRegion *region) {
-  ID.AddPointer(store);
+                                  const StoreRef &store,
+                                  const TypedRegion *region) {
+  ID.AddPointer(store.getStore());
   ID.AddPointer(region);
 }
 
@@ -124,7 +125,7 @@ BasicValueFactory::getCompoundValData(QualType T,
 }
 
 const LazyCompoundValData*
-BasicValueFactory::getLazyCompoundValData(const void *store,
+BasicValueFactory::getLazyCompoundValData(const StoreRef &store,
                                           const TypedRegion *region) {
   llvm::FoldingSetNodeID ID;
   LazyCompoundValData::Profile(ID, store, region);
index 19e0e125721549e2b0eb69f88df9a065577df22c..96a9d4f5d3e4832f99bf13369a4838ebca4cdfad 100644 (file)
@@ -1250,12 +1250,12 @@ SVal RegionStoreManager::RetrieveLazySymbol(const TypedRegion *R) {
 SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
   QualType T = R->getValueType();
   assert(T->isStructureOrClassType());
-  return svalBuilder.makeLazyCompoundVal(store, R);
+  return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R);
 }
 
 SVal RegionStoreManager::RetrieveArray(Store store, const TypedRegion * R) {
   assert(Ctx.getAsConstantArrayType(R->getValueType()));
-  return svalBuilder.makeLazyCompoundVal(store, R);
+  return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R);
 }
 
 //===----------------------------------------------------------------------===//
@@ -1378,7 +1378,8 @@ StoreRef RegionStoreManager::BindArray(Store store, const TypedRegion* R,
 
     // Treat the string as a lazy compound value.
     nonloc::LazyCompoundVal LCV =
-      cast<nonloc::LazyCompoundVal>(svalBuilder.makeLazyCompoundVal(store, S));
+      cast<nonloc::LazyCompoundVal>(svalBuilder.
+                                makeLazyCompoundVal(StoreRef(store, *this), S));
     return CopyLazyBindings(LCV, store, R);
   }
 
index 5544432f463267c4cc95a0aee5bd4f2d129faeaf..18ec0b39785a13ad8fcf11d1771e7876db2080e0 100644 (file)
@@ -1237,3 +1237,20 @@ void pr9048(pr9048_cdev_t dev, struct pr9048_diskslices * ssp, unsigned int slic
   }
 }
 
+// Test Store reference counting in the presence of Lazy compound values.
+// This previously caused an infinite recursion.
+typedef struct {} Rdar_9103310_A;
+typedef struct Rdar_9103310_B Rdar_9103310_B_t;
+struct Rdar_9103310_B {
+  unsigned char           Rdar_9103310_C[101];
+};
+void Rdar_9103310_E(Rdar_9103310_A * x, struct Rdar_9103310_C * b) { // expected-warning {{declaration of 'struct Rdar_9103310_C' will not be visible outside of this function}}
+  char Rdar_9103310_D[4][4] = { "a", "b", "c", "d"};
+  int i;
+  Rdar_9103310_B_t *y = (Rdar_9103310_B_t *) x;
+  for (i = 0; i < 101; i++) {
+    Rdar_9103310_F(b, "%2d%s ", (y->Rdar_9103310_C[i]) / 4, Rdar_9103310_D[(y->Rdar_9103310_C[i]) % 4]); // expected-warning {{implicit declaration of function 'Rdar_9103310_F' is invalid in C99}}
+  }
+}
+
+