diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 92 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 83 |
2 files changed, 9 insertions, 166 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index da060414cd4..54b12410aa5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -145,8 +145,7 @@ public: static ProgramStateRef InvalidateBuffer(CheckerContext &C, ProgramStateRef state, const Expr *Ex, SVal V, - bool IsSourceBuffer, - const Expr *Size); + bool IsSourceBuffer); static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx, const MemRegion *MR); @@ -194,14 +193,6 @@ public: ProgramStateRef state, NonLoc left, NonLoc right) const; - - // Return true if destination buffer of copy function is in bound. - // Expects SVal of Size to be positive and unsigned. - // Expects SVal of FirstBuf to be a FieldRegion. - static bool IsFirstBufInBound(CheckerContext &C, - ProgramStateRef state, - const Expr *FirstBuf, - const Expr *Size); }; } //end anonymous namespace @@ -823,68 +814,10 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, return strRegion->getStringLiteral(); } -bool CStringChecker::IsFirstBufInBound(CheckerContext &C, - ProgramStateRef state, - const Expr *FirstBuf, - const Expr *Size) { - - // Originally copied from CheckBufferAccess and CheckLocation. - SValBuilder &svalBuilder = C.getSValBuilder(); - ASTContext &Ctx = svalBuilder.getContext(); - const LocationContext *LCtx = C.getLocationContext(); - - QualType sizeTy = Size->getType(); - QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); - SVal BufVal = state->getSVal(FirstBuf, LCtx); - - SVal LengthVal = state->getSVal(Size, LCtx); - // Cast is safe as the size argument to copy functions are of integral type. - NonLoc Length = LengthVal.castAs<NonLoc>(); - - // Compute the offset of the last element to be accessed: size-1. - NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>(); - NonLoc LastOffset = - svalBuilder.evalBinOpNN(state, BO_Sub, Length, One, sizeTy) - .castAs<NonLoc>(); - - // Check that the first buffer is sufficiently long. - SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); - // Cast is safe as caller checks BufVal is a MemRegionVal. - Loc BufLoc = BufStart.castAs<Loc>(); - - SVal BufEnd = - svalBuilder.evalBinOpLN(state, BO_Add, BufLoc, LastOffset, PtrTy); - - // Check for out of bound array element access. - const MemRegion *R = BufEnd.getAsRegion(); - // BufStart is a MemRegionVal so BufEnd should be one too. - assert(R && "BufEnd should be a MemRegion"); - - // Cast is safe as BufVal's region is a FieldRegion. - const ElementRegion *ER = cast<ElementRegion>(R); - - assert(ER->getValueType() == C.getASTContext().CharTy && - "IsFirstBufInBound should only be called with char* ElementRegions"); - - // Get the size of the array. - const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); - SVal Extent = - svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); - DefinedOrUnknownSVal ExtentSize = Extent.castAs<DefinedOrUnknownSVal>(); - - // Get the index of the accessed element. - DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>(); - - ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize, true); - - return static_cast<bool>(StInBound); -} - ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C, ProgramStateRef state, const Expr *E, SVal V, - bool IsSourceBuffer, - const Expr *Size) { + bool IsSourceBuffer) { Optional<Loc> L = V.getAs<Loc>(); if (!L) return state; @@ -914,16 +847,6 @@ ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C, RegionAndSymbolInvalidationTraits::TK_PreserveContents); ITraits.setTrait(R, RegionAndSymbolInvalidationTraits::TK_SuppressEscape); CausesPointerEscape = true; - } else { - const MemRegion::Kind& K = R->getKind(); - if (K == MemRegion::FieldRegionKind) - if (Size && IsFirstBufInBound(C, state, E, Size)) { - // If destination buffer is a field region and access is in bound, - // do not invalidate its super region. - ITraits.setTrait( - R, - RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion); - } } return state->invalidateRegions(R, E, C.blockCount(), LCtx, @@ -1077,12 +1000,12 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, // This would probably remove any existing bindings past the end of the // copied region, but that's still an improvement over blank invalidation. state = InvalidateBuffer(C, state, Dest, C.getSVal(Dest), - /*IsSourceBuffer*/false, Size); + /*IsSourceBuffer*/false); // Invalidate the source (const-invalidation without const-pointer-escaping // the address of the top-level region). state = InvalidateBuffer(C, state, Source, C.getSVal(Source), - /*IsSourceBuffer*/true, nullptr); + /*IsSourceBuffer*/true); C.addTransition(state); } @@ -1697,12 +1620,11 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, // This would probably remove any existing bindings past the end of the // string, but that's still an improvement over blank invalidation. state = InvalidateBuffer(C, state, Dst, *dstRegVal, - /*IsSourceBuffer*/false, nullptr); + /*IsSourceBuffer*/false); // Invalidate the source (const-invalidation without const-pointer-escaping // the address of the top-level region). - state = InvalidateBuffer(C, state, srcExpr, srcVal, /*IsSourceBuffer*/true, - nullptr); + state = InvalidateBuffer(C, state, srcExpr, srcVal, /*IsSourceBuffer*/true); // Set the C string length of the destination, if we know it. if (isBounded && !isAppending) { @@ -1926,7 +1848,7 @@ void CStringChecker::evalStrsep(CheckerContext &C, const CallExpr *CE) const { // Invalidate the search string, representing the change of one delimiter // character to NUL. State = InvalidateBuffer(C, State, SearchStrPtr, Result, - /*IsSourceBuffer*/false, nullptr); + /*IsSourceBuffer*/false); // Overwrite the search string pointer. The new value is either an address // further along in the same string, or NULL if there are no more tokens. diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 0d403bc190c..41783245435 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -710,7 +710,8 @@ public: } bool AddToWorkList(const MemRegion *R) { - return static_cast<DERIVED*>(this)->AddToWorkList(R); + const MemRegion *BaseR = R->getBaseRegion(); + return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR)); } void RunWorkList() { @@ -955,20 +956,9 @@ public: void VisitCluster(const MemRegion *baseR, const ClusterBindings *C); void VisitBinding(SVal V); - - using ClusterAnalysis::AddToWorkList; - - bool AddToWorkList(const MemRegion *R); }; } -bool invalidateRegionsWorker::AddToWorkList(const MemRegion *R) { - bool doNotInvalidateSuperRegion = ITraits.hasTrait( - R, RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion); - const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion(); - return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR)); -} - void invalidateRegionsWorker::VisitBinding(SVal V) { // A symbol? Mark it touched by the invalidation. if (SymbolRef Sym = V.getAsSymbol()) @@ -1081,66 +1071,6 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR, } if (const ArrayType *AT = Ctx.getAsArrayType(T)) { - bool doNotInvalidateSuperRegion = ITraits.hasTrait( - baseR, - RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion); - - if (doNotInvalidateSuperRegion) { - // We are not doing blank invalidation of the whole array region so we - // have to manually invalidate each elements. - Optional<uint64_t> NumElements; - - // Compute lower and upper offsets for region within array. - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) - NumElements = CAT->getSize().getZExtValue(); - if (!NumElements) // We are not dealing with a constant size array - goto conjure_default; - QualType ElementTy = AT->getElementType(); - uint64_t ElemSize = Ctx.getTypeSize(ElementTy); - const RegionOffset &RO = baseR->getAsOffset(); - const MemRegion *SuperR = baseR->getBaseRegion(); - if (RO.hasSymbolicOffset()) { - // If base region has a symbolic offset, - // we revert to invalidating the super region. - if (SuperR) - AddToWorkList(SuperR); - goto conjure_default; - } - assert(RO.getOffset() >= 0 && "Offset should not be negative"); - uint64_t LowerOffset = RO.getOffset(); - uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize; - - // Invalidate regions which are within array boundaries, - // or have a symbolic offset. - if (!SuperR) - goto conjure_default; - - const ClusterBindings *C = B.lookup(SuperR); - if (!C) - goto conjure_default; - - for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E; - ++I) { - const BindingKey &BK = I.getKey(); - Optional<uint64_t> ROffset = - BK.hasSymbolicOffset() ? Optional<uint64_t>() : BK.getOffset(); - // Check offset is not symbolic and within array's boundaries. - // Handles arrays of 0 elements and of 0-sized elements as well. - if (!ROffset || - (ROffset && - ((*ROffset >= LowerOffset && *ROffset < UpperOffset) || - (LowerOffset == UpperOffset && *ROffset == LowerOffset)))) { - B = B.removeBinding(I.getKey()); - // Bound symbolic regions need to be invalidated for dead symbol - // detection. - SVal V = I.getData(); - const MemRegion *R = V.getAsRegion(); - if (R && isa<SymbolicRegion>(R)) - VisitBinding(V); - } - } - } - conjure_default: // Set the default value of the array to conjured symbol. DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(baseR, Ex, LCtx, @@ -2257,20 +2187,11 @@ public: void VisitCluster(const MemRegion *baseR, const ClusterBindings *C); using ClusterAnalysis<removeDeadBindingsWorker>::VisitCluster; - using ClusterAnalysis::AddToWorkList; - - bool AddToWorkList(const MemRegion *R); - bool UpdatePostponed(); void VisitBinding(SVal V); }; } -bool removeDeadBindingsWorker::AddToWorkList(const MemRegion *R) { - const MemRegion *BaseR = R->getBaseRegion(); - return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR)); -} - void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C) { |

