summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp92
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp83
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) {
OpenPOWER on IntegriCloud