@@ -389,15 +389,26 @@ static std::optional<int64_t> getConcreteValue(std::optional<NonLoc> SV) {
389
389
}
390
390
391
391
static 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);
394
395
395
- if (auto ConcreteOffset = getConcreteValue (Offset))
396
+ std::string OffsetStr = " " , ElemInfoStr = " " ;
397
+ if (std::optional<int64_t > ConcreteOffset = getConcreteValue (Offset)) {
396
398
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
+ }
397
408
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 )};
401
412
}
402
413
403
414
// / 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,
419
430
return true ;
420
431
}
421
432
422
- static Messages getExceedsMsgs (ASTContext &ACtx, const MemSpaceRegion *Space,
433
+ static Messages getExceedsMsgs (const MemSpaceRegion *Space,
423
434
const SubRegion *Region, NonLoc Offset,
424
- NonLoc Extent, SVal Location ,
425
- bool AlsoMentionUnderflow ) {
435
+ NonLoc Extent, bool AlsoMentionUnderflow ,
436
+ QualType ElemType, int64_t ElemSize ) {
426
437
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 ();
430
438
431
439
std::optional<int64_t > OffsetN = getConcreteValue (Offset);
432
440
std::optional<int64_t > ExtentN = getConcreteValue (Extent);
433
441
434
- int64_t ElemSize = ACtx.getTypeSizeInChars (ElemType).getQuantity ();
435
-
436
442
bool UseByteOffsets = !tryDividePair (OffsetN, ExtentN, ElemSize);
437
443
const char *OffsetOrIndex = UseByteOffsets ? " byte offset" : " index" ;
438
444
@@ -585,6 +591,13 @@ void ArrayBoundChecker::performCheck(const Expr *E, CheckerContext &C) const {
585
591
if (!RawOffset)
586
592
return ;
587
593
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
+
588
601
auto [Reg, ByteOffset] = *RawOffset;
589
602
590
603
// 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 {
635
648
} else {
636
649
if (!WithinLowerBound) {
637
650
// ...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);
639
653
reportOOB (C, PrecedesLowerBound, Msgs, ByteOffset, std::nullopt );
640
654
return ;
641
655
}
@@ -678,8 +692,8 @@ void ArrayBoundChecker::performCheck(const Expr *E, CheckerContext &C) const {
678
692
}
679
693
680
694
Messages Msgs =
681
- getExceedsMsgs (C. getASTContext (), Space, Reg, ByteOffset,
682
- *KnownSize, Location, AlsoMentionUnderflow );
695
+ getExceedsMsgs (Space, Reg, ByteOffset, *KnownSize ,
696
+ AlsoMentionUnderflow, ElemType, ElemSize );
683
697
reportOOB (C, ExceedsUpperBound, Msgs, ByteOffset, KnownSize);
684
698
return ;
685
699
}
0 commit comments