@@ -389,15 +389,26 @@ static std::optional<int64_t> getConcreteValue(std::optional<NonLoc> SV) {
389389}
390390
391391static Messages getPrecedesMsgs (const MemSpaceRegion *Space,
392- const SubRegion *Region, NonLoc Offset) {
393- std::string RegName = getRegionName (Space, Region), OffsetStr = " " ;
392+ const SubRegion *Region, NonLoc Offset,
393+ QualType ElemType, int64_t ElemSize) {
394+ std::string RegName = getRegionName (Space, Region);
394395
395- if (auto ConcreteOffset = getConcreteValue (Offset))
396+ std::string OffsetStr = " " , ElemInfoStr = " " ;
397+ if (std::optional<int64_t > ConcreteOffset = getConcreteValue (Offset)) {
396398 OffsetStr = formatv (" {0}" , ConcreteOffset);
399+ if (*ConcreteOffset % ElemSize == 0 ) {
400+ int64_t Count = *ConcreteOffset / ElemSize;
401+ if (Count != -1 )
402+ ElemInfoStr =
403+ formatv (" = {0} * sizeof({1})" , Count, ElemType.getAsString ());
404+ else
405+ ElemInfoStr = formatv (" = -sizeof({0})" , ElemType.getAsString ());
406+ }
407+ }
397408
398- return {
399- formatv (" Out of bound access to memory preceding {0} " , RegName) ,
400- formatv ( " Access of {0} at negative byte offset{1} " , RegName, OffsetStr)};
409+ return {formatv ( " Out of bound access to memory preceding {0} " , RegName),
410+ formatv (" Access of {0} at negative byte offset{1}{2} " , RegName,
411+ OffsetStr, ElemInfoStr )};
401412}
402413
403414// / Try to divide `Val1` and `Val2` (in place) by `Divisor` and return true if
@@ -419,20 +430,15 @@ static bool tryDividePair(std::optional<int64_t> &Val1,
419430 return true ;
420431}
421432
422- static Messages getExceedsMsgs (ASTContext &ACtx, const MemSpaceRegion *Space,
433+ static Messages getExceedsMsgs (const MemSpaceRegion *Space,
423434 const SubRegion *Region, NonLoc Offset,
424- NonLoc Extent, SVal Location ,
425- bool AlsoMentionUnderflow ) {
435+ NonLoc Extent, bool AlsoMentionUnderflow ,
436+ QualType ElemType, int64_t ElemSize ) {
426437 std::string RegName = getRegionName (Space, Region);
427- const auto *EReg = Location.getAsRegion ()->getAs <ElementRegion>();
428- assert (EReg && " this checker only handles element access" );
429- QualType ElemType = EReg->getElementType ();
430438
431439 std::optional<int64_t > OffsetN = getConcreteValue (Offset);
432440 std::optional<int64_t > ExtentN = getConcreteValue (Extent);
433441
434- int64_t ElemSize = ACtx.getTypeSizeInChars (ElemType).getQuantity ();
435-
436442 bool UseByteOffsets = !tryDividePair (OffsetN, ExtentN, ElemSize);
437443 const char *OffsetOrIndex = UseByteOffsets ? " byte offset" : " index" ;
438444
@@ -585,6 +591,13 @@ void ArrayBoundChecker::performCheck(const Expr *E, CheckerContext &C) const {
585591 if (!RawOffset)
586592 return ;
587593
594+ const auto *EReg = Location.getAsRegion ()->getAs <ElementRegion>();
595+ assert (EReg && " this checker only handles element access" );
596+ QualType ElemType = EReg->getElementType ();
597+
598+ int64_t ElemSize =
599+ C.getASTContext ().getTypeSizeInChars (ElemType).getQuantity ();
600+
588601 auto [Reg, ByteOffset] = *RawOffset;
589602
590603 // The state updates will be reported as a single note tag, which will be
@@ -635,7 +648,8 @@ void ArrayBoundChecker::performCheck(const Expr *E, CheckerContext &C) const {
635648 } else {
636649 if (!WithinLowerBound) {
637650 // ...and it cannot be valid (>= 0), so report an error.
638- Messages Msgs = getPrecedesMsgs (Space, Reg, ByteOffset);
651+ Messages Msgs =
652+ getPrecedesMsgs (Space, Reg, ByteOffset, ElemType, ElemSize);
639653 reportOOB (C, PrecedesLowerBound, Msgs, ByteOffset, std::nullopt );
640654 return ;
641655 }
@@ -678,8 +692,8 @@ void ArrayBoundChecker::performCheck(const Expr *E, CheckerContext &C) const {
678692 }
679693
680694 Messages Msgs =
681- getExceedsMsgs (C. getASTContext (), Space, Reg, ByteOffset,
682- *KnownSize, Location, AlsoMentionUnderflow );
695+ getExceedsMsgs (Space, Reg, ByteOffset, *KnownSize ,
696+ AlsoMentionUnderflow, ElemType, ElemSize );
683697 reportOOB (C, ExceedsUpperBound, Msgs, ByteOffset, KnownSize);
684698 return ;
685699 }
0 commit comments