[UBSan] Don't overflow when calculating memory range that should be dumped

llvm-svn: 217703
This commit is contained in:
Alexey Samsonov 2014-09-12 19:51:26 +00:00
parent 63e3a29ff3
commit 0e8364e912
1 changed files with 16 additions and 6 deletions

View File

@ -193,24 +193,34 @@ static Range *upperBound(MemoryLocation Loc, Range *Ranges,
return Best; return Best;
} }
static inline uptr subtractNoOverflow(uptr LHS, uptr RHS) {
return (LHS < RHS) ? 0 : LHS - RHS;
}
static inline uptr addNoOverflow(uptr LHS, uptr RHS) {
const uptr Limit = (uptr)-1;
return (LHS > Limit - RHS) ? Limit : LHS + RHS;
}
/// Render a snippet of the address space near a location. /// Render a snippet of the address space near a location.
static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc, static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc,
Range *Ranges, unsigned NumRanges, Range *Ranges, unsigned NumRanges,
const Diag::Arg *Args) { const Diag::Arg *Args) {
const unsigned BytesToShow = 32;
const unsigned MinBytesNearLoc = 4;
// Show at least the 8 bytes surrounding Loc. // Show at least the 8 bytes surrounding Loc.
MemoryLocation Min = Loc - MinBytesNearLoc, Max = Loc + MinBytesNearLoc; const unsigned MinBytesNearLoc = 4;
MemoryLocation Min = subtractNoOverflow(Loc, MinBytesNearLoc);
MemoryLocation Max = addNoOverflow(Loc, MinBytesNearLoc);
MemoryLocation OrigMin = Min;
for (unsigned I = 0; I < NumRanges; ++I) { for (unsigned I = 0; I < NumRanges; ++I) {
Min = __sanitizer::Min(Ranges[I].getStart().getMemoryLocation(), Min); Min = __sanitizer::Min(Ranges[I].getStart().getMemoryLocation(), Min);
Max = __sanitizer::Max(Ranges[I].getEnd().getMemoryLocation(), Max); Max = __sanitizer::Max(Ranges[I].getEnd().getMemoryLocation(), Max);
} }
// If we have too many interesting bytes, prefer to show bytes after Loc. // If we have too many interesting bytes, prefer to show bytes after Loc.
const unsigned BytesToShow = 32;
if (Max - Min > BytesToShow) if (Max - Min > BytesToShow)
Min = __sanitizer::Min(Max - BytesToShow, Loc - MinBytesNearLoc); Min = __sanitizer::Min(Max - BytesToShow, OrigMin);
Max = Min + BytesToShow; Max = addNoOverflow(Min, BytesToShow);
// Emit data. // Emit data.
for (uptr P = Min; P != Max; ++P) { for (uptr P = Min; P != Max; ++P) {