[analyzer] Replace adjacent assumeInBound calls to assumeInBoundDual

This is to minimize superfluous assume calls.

Depends on D124758

Differential Revision: https://reviews.llvm.org/D124761
This commit is contained in:
Gabor Marton 2022-05-02 13:32:28 +02:00
parent 1c1c1e25f9
commit 34ac048aef
7 changed files with 32 additions and 19 deletions

View File

@ -225,6 +225,10 @@ public:
LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef>
assume(DefinedOrUnknownSVal cond) const;
LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef>
assumeInBoundDual(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound,
QualType IndexType = QualType()) const;
LLVM_NODISCARD ProgramStateRef
assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound,
bool assumption, QualType IndexType = QualType()) const;

View File

@ -58,8 +58,8 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType());
ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false);
ProgramStateRef StInBound, StOutBound;
std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, ElementCount);
if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateErrorNode(StOutBound);
if (!N)

View File

@ -355,8 +355,8 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
// Get the index of the accessed element.
DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
ProgramStateRef StInBound, StOutBound;
std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, Size);
if (StOutBound && !StInBound) {
// These checks are either enabled by the CString out-of-bounds checker
// explicitly or implicitly by the Malloc checker.

View File

@ -137,8 +137,8 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
// Now, check if 'Idx in [0, Size-1]'.
const QualType T = IdxExpr->getType();
ProgramStateRef StInBound = State->assumeInBound(Idx, *Size, true, T);
ProgramStateRef StOutBound = State->assumeInBound(Idx, *Size, false, T);
ProgramStateRef StInBound, StOutBound;
std::tie(StInBound, StOutBound) = State->assumeInBoundDual(Idx, *Size, T);
if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateErrorNode(StOutBound);
if (!N)

View File

@ -64,8 +64,8 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
if (Idx == ElementCount)
return;
ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false);
ProgramStateRef StInBound, StOutBound;
std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, ElementCount);
if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateErrorNode(StOutBound);

View File

@ -53,8 +53,8 @@ static bool isArrayIndexOutOfBounds(CheckerContext &C, const Expr *Ex) {
DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType());
ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false);
ProgramStateRef StInBound, StOutBound;
std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, ElementCount);
return StOutBound && !StInBound;
}

View File

@ -314,12 +314,12 @@ ProgramStateRef ProgramState::BindExpr(const Stmt *S,
return getStateManager().getPersistentState(NewSt);
}
ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
DefinedOrUnknownSVal UpperBound,
bool Assumption,
QualType indexTy) const {
LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef>
ProgramState::assumeInBoundDual(DefinedOrUnknownSVal Idx,
DefinedOrUnknownSVal UpperBound,
QualType indexTy) const {
if (Idx.isUnknown() || UpperBound.isUnknown())
return this;
return {this, this};
// Build an expression for 0 <= Idx < UpperBound.
// This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
@ -338,7 +338,7 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
Idx.castAs<NonLoc>(), Min, indexTy);
if (newIdx.isUnknownOrUndef())
return this;
return {this, this};
// Adjust the upper bound.
SVal newBound =
@ -346,17 +346,26 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
Min, indexTy);
if (newBound.isUnknownOrUndef())
return this;
return {this, this};
// Build the actual comparison.
SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
newBound.castAs<NonLoc>(), Ctx.IntTy);
if (inBound.isUnknownOrUndef())
return this;
return {this, this};
// Finally, let the constraint manager take care of it.
ConstraintManager &CM = SM.getConstraintManager();
return CM.assume(this, inBound.castAs<DefinedSVal>(), Assumption);
return CM.assumeDual(this, inBound.castAs<DefinedSVal>());
}
ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
DefinedOrUnknownSVal UpperBound,
bool Assumption,
QualType indexTy) const {
std::pair<ProgramStateRef, ProgramStateRef> R =
assumeInBoundDual(Idx, UpperBound, indexTy);
return Assumption ? R.first : R.second;
}
ConditionTruthVal ProgramState::isNonNull(SVal V) const {