[PATCH] D148355: [analyzer] Fix comparison logic in ArrayBoundCheckerV2
Balázs Benics via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 21 07:40:44 PDT 2023
steakhal added a comment.
I like this. Looks really solid.
I only had style nitpicks.
Have you run measurements?
After that we could land it, I think.
FYI: I'll also schedule a test run with this patch. You should expect the results in a week - not because it takes that long, but because I need to find time for evaluating it xD.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:57-61
+ RegionRawOffsetV2(const SubRegion *base, SVal offset)
+ : baseRegion(base), byteOffset(offset) {
+ if (baseRegion)
+ assert(llvm::isa<NonLoc>(byteOffset));
+ }
----------------
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:121-135
+ if (auto ConcreteTh = Threshold.getAs<nonloc::ConcreteInt>()) {
+ std::tie(Value, Threshold) = getSimplifiedOffsets(Value, *ConcreteTh, SVB);
+ }
+ if (auto ConcreteTh = Threshold.getAs<nonloc::ConcreteInt>()) {
+ QualType T = Value.getType(SVB.getContext());
+ if (T->isUnsignedIntegerType() && ConcreteTh->getValue().isNegative()) {
+ // In this case we reduced the bound check to a comparison of the form
----------------
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:136-137
+ }
+ SVal belowThreshold =
+ SVB.evalBinOpNN(State, BO_LT, Value, Threshold, SVB.getConditionType());
+
----------------
steakhal wrote:
>
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:136-140
+ SVal belowThreshold =
+ SVB.evalBinOpNN(State, BO_LT, Value, Threshold, SVB.getConditionType());
+
+ if (std::optional<NonLoc> belowThresholdNL = belowThreshold.getAs<NonLoc>())
+ return State->assume(*belowThresholdNL);
----------------
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:167-168
- NonLoc rawOffsetVal = rawOffset.getByteOffset();
-
- // CHECK LOWER BOUND: Is byteOffset < extent begin?
- // If so, we are doing a load/store
- // before the first valid offset in the memory region.
+ // At this point we know that rawOffset is not default-constructed so we may
+ // call this:
+ NonLoc ByteOffset = rawOffset.getByteOffset();
----------------
I don't think we need an explanation here.
BTW This "optional-like" `RegionRawOffsetV2` makes me angry. It should be an `std::optional<RegionRawOffsetV2>` in the first place.
You don't need to take actions, I'm just ranting...
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:173
+ const MemSpaceRegion *SR = rawOffset.getRegion()->getMemorySpace();
+ if (SR->getKind() != MemRegion::UnknownSpaceRegionKind) {
+ // a pointer to UnknownSpaceRegionKind may point to the middle of
----------------
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:174-175
+ if (SR->getKind() != MemRegion::UnknownSpaceRegionKind) {
+ // a pointer to UnknownSpaceRegionKind may point to the middle of
+ // an allocated region
----------------
Good point.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:183
if (state_precedesLowerBound && !state_withinLowerBound) {
+ // We know that the index definitely precedes the lower bound
reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes);
----------------
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:195
+ getDynamicExtent(state, rawOffset.getRegion(), svalBuilder);
+ if (std::optional<NonLoc> KnownSize = Size.getAs<NonLoc>()) {
+ ProgramStateRef state_withinUpperBound, state_exceedsUpperBound;
----------------
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:196-198
+ ProgramStateRef state_withinUpperBound, state_exceedsUpperBound;
+ std::tie(state_withinUpperBound, state_exceedsUpperBound) =
+ compareValueToThreshold(state, ByteOffset, *KnownSize, svalBuilder);
----------------
I think as we don't plan to overwrite/assign to these states, we could just use structured bindings.
I think that should be preferred over `std::tie()`-ing think. That is only not widespread because we just recently moved to C++17.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:212-215
}
- assert(state_withinUpperBound);
- state = state_withinUpperBound;
+ if (state_withinUpperBound)
+ state = state_withinUpperBound;
----------------
You just left the guarded block in the previous line.
By moving this statement there you could spare the `if`.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:310-311
offset = getValue(offset, svalBuilder);
if (!offset.isUnknownOrUndef())
return RegionRawOffsetV2(subReg, offset);
}
----------------
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D148355/new/
https://reviews.llvm.org/D148355
More information about the cfe-commits
mailing list