static analyzer: Fix use-after-free bug in RegionStore involving LazyCompoundValueData not reference counting Store objects.
llvm-svn: 127288
This commit is contained in:
parent
ea5ebfed15
commit
4bb6c6b37e
|
@ -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() {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue