From: Ted Kremenek Date: Tue, 8 Mar 2011 23:18:00 +0000 (+0000) Subject: static analyzer: Fix use-after-free bug in RegionStore involving LazyCompoundValueDat... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cf333339615da345c2ed6e873d94a501810d9f3f;p=clang static analyzer: Fix use-after-free bug in RegionStore involving LazyCompoundValueData not reference counting Store objects. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127288 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index a4327e127f..65fbfcc912 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -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 Vals); - const LazyCompoundValData *getLazyCompoundValData(const void *store, + const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store, const TypedRegion *region); llvm::ImmutableList getEmptySValList() { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 4b08f20640..0f9e56aa2f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -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)); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 0251311c27..21c6ae760c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -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 index 0000000000..0662eadc93 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h @@ -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 + +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 diff --git a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp index 6315d83d89..d29c86adcf 100644 --- a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp +++ b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp @@ -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); diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 19e0e12572..96a9d4f5d3 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -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(svalBuilder.makeLazyCompoundVal(store, S)); + cast(svalBuilder. + makeLazyCompoundVal(StoreRef(store, *this), S)); return CopyLazyBindings(LCV, store, R); } diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index 5544432f46..18ec0b3978 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -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}} + } +} + +