From 8667052a53a47a6290dc9ae98e5c3d9277df5f4a Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 10 May 2012 22:02:39 +0000 Subject: [PATCH] Fix insidious RegionStore bug where we (a) didn't handle vector types and (b) had a horrible bug in GetLazyBindings where we falsely appended a field suffix when traversing 3 or more layers of lazy bindings. I don't have a reduced test case yet; but I have added the original source to an internal regression test suite. I'll see about coming up with a reduced test case. Fixes (for real). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156580 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/RegionStore.cpp | 78 +++++++++++++++++++++---- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 1b941cc680..47fb70a341 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -302,6 +302,9 @@ public: // Part of public interface to class. /// BindStruct - Bind a compound value to a structure. StoreRef BindStruct(Store store, const TypedValueRegion* R, SVal V); + /// BindVector - Bind a compound value to a vector. + StoreRef BindVector(Store store, const TypedValueRegion* R, SVal V); + StoreRef BindArray(Store store, const TypedValueRegion* R, SVal V); /// KillStruct - Set the entire struct to unknown. @@ -372,7 +375,8 @@ public: // Part of public interface to class. /// Get the state and region whose binding this region R corresponds to. std::pair GetLazyBinding(RegionBindings B, const MemRegion *R, - const MemRegion *originalRegion); + const MemRegion *originalRegion, + bool includeSuffix = false); StoreRef CopyLazyBindings(nonloc::LazyCompoundVal V, Store store, const TypedRegion *R); @@ -1108,7 +1112,8 @@ SVal RegionStoreManager::getBinding(Store store, Loc L, QualType T) { std::pair RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R, - const MemRegion *originalRegion) { + const MemRegion *originalRegion, + bool includeSuffix) { if (originalRegion != R) { if (Optional OV = getDefaultBinding(B, R)) { @@ -1130,9 +1135,13 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R, const std::pair &X = GetLazyBinding(B, FR->getSuperRegion(), originalRegion); - if (X.second) - return std::make_pair(X.first, - MRMgr.getFieldRegionWithSuper(FR, X.second)); + if (X.second) { + if (includeSuffix) + return std::make_pair(X.first, + MRMgr.getFieldRegionWithSuper(FR, X.second)); + return X; + } + } // C++ base object region is another kind of region that we should blast // through to look for lazy compound value. It is like a field region. @@ -1141,9 +1150,13 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R, const std::pair &X = GetLazyBinding(B, baseReg->getSuperRegion(), originalRegion); - if (X.second) - return std::make_pair(X.first, - MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second)); + if (X.second) { + if (includeSuffix) + return std::make_pair(X.first, + MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, + X.second)); + return X; + } } // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is @@ -1492,9 +1505,13 @@ StoreRef RegionStoreManager::Bind(Store store, Loc L, SVal V) { const MemRegion *R = cast(L).getRegion(); // Check if the region is a struct region. - if (const TypedValueRegion* TR = dyn_cast(R)) - if (TR->getValueType()->isStructureOrClassType()) + if (const TypedValueRegion* TR = dyn_cast(R)) { + QualType Ty = TR->getValueType(); + if (Ty->isStructureOrClassType()) return BindStruct(store, TR, V); + if (Ty->isVectorType()) + return BindVector(store, TR, V); + } if (const ElementRegion *ER = dyn_cast(R)) { if (ER->getIndex().isZeroConstant()) { @@ -1638,6 +1655,47 @@ StoreRef RegionStoreManager::BindArray(Store store, const TypedValueRegion* R, return newStore; } +StoreRef RegionStoreManager::BindVector(Store store, const TypedValueRegion* R, + SVal V) { + QualType T = R->getValueType(); + assert(T->isVectorType()); + const VectorType *VT = T->getAs(); // Use getAs for typedefs. + + // Handle lazy compound values. + if (nonloc::LazyCompoundVal *LCV = dyn_cast(&V)) + return CopyLazyBindings(*LCV, store, R); + + // We may get non-CompoundVal accidentally due to imprecise cast logic or + // that we are binding symbolic struct value. Kill the field values, and if + // the value is symbolic go and bind it as a "default" binding. + if (V.isUnknown() || !isa(V)) { + SVal SV = isa(V) ? V : UnknownVal(); + return KillStruct(store, R, SV); + } + + QualType ElemType = VT->getElementType(); + nonloc::CompoundVal& CV = cast(V); + nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); + unsigned index = 0, numElements = VT->getNumElements(); + StoreRef newStore(store, *this); + + for ( ; index != numElements ; ++index) { + if (VI == VE) + break; + + NonLoc Idx = svalBuilder.makeArrayIndex(index); + const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx); + + if (ElemType->isArrayType()) + newStore = BindArray(newStore.getStore(), ER, *VI); + else if (ElemType->isStructureOrClassType()) + newStore = BindStruct(newStore.getStore(), ER, *VI); + else + newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(ER), *VI); + } + return newStore; +} + StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R, SVal V) { -- 2.40.0