Lines Matching +full:1 +full:br +full:- +full:10

1 //== ArrayBoundCheckerV2.cpp ------------------------------------*- C++ -*--==//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines ArrayBoundCheckerV2, which is a path-sensitive check
10 // which looks for an out-of-bound array element access.
12 //===----------------------------------------------------------------------===//
47 const MemRegion *SubscriptBaseReg = C.getSVal(ASE->getBase()).getAsRegion(); in determineElementType()
53 if (isa<ElementRegion>(SubscriptBaseReg->StripCasts())) in determineElementType()
56 return ASE->getType(); in determineElementType()
91 std::string getMessage(PathSensitiveBugReport &BR) const;
94 /// on some symbol which is interesting within the bug report `BR`.
95 /// In particular, this returns true when `Sym` is interesting within `BR`;
97 /// constants and a single symbolic operand which is interesting (in `BR`).
98 /// We need to use this instead of plain `BR.isInteresting()` because if we
100 /// int array[10];
102 /// return array[arg] && array[arg + 10];
104 /// then the byte offsets are `arg * 4` and `(arg + 10) * 4`, which are not
105 /// sub-expressions of each other (but `getSimplifiedOffsets` is smart enough
108 PathSensitiveBugReport &BR);
110 PathSensitiveBugReport &BR) { in providesInformationAboutInteresting() argument
111 return providesInformationAboutInteresting(SV.getAsSymbol(), BR); in providesInformationAboutInteresting()
129 BugType BT{this, "Out-of-bound access"};
130 BugType TaintBT{this, "Out-of-bound access", categories::TaintedData};
138 static void markPartsInteresting(PathSensitiveBugReport &BR,
154 if (E->getOpcode() == UO_Deref) in checkPostStmt()
158 if (E->isArrow()) in checkPostStmt()
159 performCheck(E->getBase(), C); in checkPostStmt()
185 const auto Index = CurRegion->getIndex().getAs<NonLoc>(); in computeOffset()
189 QualType ElemType = CurRegion->getElementType(); in computeOffset()
194 if (ElemType->isIncompleteType()) in computeOffset()
209 OwnerRegion = CurRegion->getSuperRegion()->getAs<SubRegion>(); in computeOffset()
235 // For example, consider a comparison "X+1 < 0", where the LHS is stored as a
238 // turn it into "X < -1", which is still always false in a mathematical sense,
240 // the rules of C++ and casts -1 to SIZE_MAX).
245 if (SymVal && SymVal->isExpression()) { in getSimplifiedOffsets()
246 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SymVal->getSymbol())) { in getSimplifiedOffsets()
248 APSIntType(extent.getValue()).convert(SIE->getRHS()); in getSimplifiedOffsets()
249 switch (SIE->getOpcode()) { in getSimplifiedOffsets()
257 nonloc::SymbolVal(SIE->getLHS()), in getSimplifiedOffsets()
262 nonloc::SymbolVal(SIE->getLHS()), in getSimplifiedOffsets()
263 svalBuilder.makeIntVal(extent.getValue() - constant), svalBuilder); in getSimplifiedOffsets()
275 return MaxV && MaxV->isNegative(); in isNegative()
280 return T->isUnsignedIntegerType(); in isUnsigned()
299 // perform automatic conversions. For example the number -1 is less than the in compareValueToThreshold()
300 // number 1000, but -1 < `1000ull` will evaluate to `false` because the `int` in compareValueToThreshold()
301 // -1 is converted to ULONGLONG_MAX. in compareValueToThreshold()
317 // FIXME: These special cases are sufficient for handling real-world in compareValueToThreshold()
334 return State->assume(*BelowThreshold); in compareValueToThreshold()
340 if (std::string RegName = Region->getDescriptiveName(); !RegName.empty()) in getRegionName()
345 if (const auto *FR = Region->getAs<FieldRegion>()) { in getRegionName()
346 if (StringRef Name = FR->getDecl()->getName(); !Name.empty()) in getRegionName()
355 isa<HeapSpaceRegion>(Region->getMemorySpace())) in getRegionName()
366 return ConcreteVal->getValue().tryExtValue(); in getConcreteValue()
383 formatv("Access of {0} at negative byte offset{1}", RegName, OffsetStr)}; in getPrecedesMsgs()
410 const auto *EReg = Location.getAsRegion()->getAs<ElementRegion>(); in getExceedsMsgs()
412 QualType ElemType = EReg->getElementType(); in getExceedsMsgs()
437 if (*ExtentN != 1) in getExceedsMsgs()
446 if (*ExtentN > 1) in getExceedsMsgs()
450 return {formatv("Out of bound access to memory {0} {1}", in getExceedsMsgs()
459 return {formatv("Potential out of bound access to {0} with tainted {1}", in getTaintMsgs()
461 formatv("Access of {0} with a tainted {1} that may be {2}too large", in getTaintMsgs()
471 return C.getNoteTag([*this](PathSensitiveBugReport &BR) -> std::string { in createNoteTag() argument
472 return getMessage(BR); in createNoteTag()
476 std::string StateUpdateReporter::getMessage(PathSensitiveBugReport &BR) const { in getMessage()
478 if (!providesInformationAboutInteresting(ByteOffsetVal, BR)) { in getMessage()
480 providesInformationAboutInteresting(*AssumedUpperBound, BR)) { in getMessage()
514 Out << " non-negative"; in getMessage()
523 Out << "the number of '" << ElementType->getAsString() in getMessage()
533 SymbolRef Sym, PathSensitiveBugReport &BR) { in providesInformationAboutInteresting() argument
536 for (SymbolRef PartSym : Sym->symbols()) { in providesInformationAboutInteresting()
539 if (BR.isInteresting(PartSym)) in providesInformationAboutInteresting()
577 const MemSpaceRegion *Space = Reg->getMemorySpace(); in performCheck()
584 // non-symbolic regions (e.g. a field subregion of a symbolic region) in in performCheck()
604 // evalBinOpNN fails to evaluate the less-than operator. in performCheck()
614 // checker will first assume that the offset is non-negative, and then in performCheck()
627 // expression that calculates the past-the-end pointer. in performCheck()
649 if (isTainted(State, ASE->getIdx(), C.getLocationContext())) in performCheck()
664 // evalBinOpNN fails to evaluate the less-than operator. in performCheck()
673 void ArrayBoundCheckerV2::markPartsInteresting(PathSensitiveBugReport &BR, in markPartsInteresting() argument
682 for (SymbolRef PartSym : Sym->symbols()) in markPartsInteresting()
683 BR.markInteresting(PartSym); in markPartsInteresting()
690 // `Sym->symbols()` (because they're only loosely connected to `Val`). in markPartsInteresting()
692 BR.markInteresting(Sym); in markPartsInteresting()
705 auto BR = std::make_unique<PathSensitiveBugReport>( in reportOOB() local
713 // - Interestingness is not applied consistently, e.g. if `array[x+10]` in reportOOB()
715 // - We get irrelevant diagnostic pieces, e.g. in the code in reportOOB()
721 markPartsInteresting(*BR, ErrorState, Offset, IsTaintBug); in reportOOB()
723 markPartsInteresting(*BR, ErrorState, *Extent, IsTaintBug); in reportOOB()
725 C.emitReport(std::move(BR)); in reportOOB()
729 SourceLocation Loc = S->getBeginLoc(); in isFromCtypeMacro()
736 if (MacroName.size() < 7 || MacroName[0] != 'i' || MacroName[1] != 's') in isFromCtypeMacro()
756 return UnaryOp && UnaryOp->getOpcode() == UO_AddrOf; in isInAddressOf()