diff options
Diffstat (limited to 'compiler-rt/lib/asan/asan_report.cc')
-rw-r--r-- | compiler-rt/lib/asan/asan_report.cc | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index 42fae9c73f0..e3bc02994ef 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -298,17 +298,58 @@ static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, in_report.ReportError(error); } +static bool IsInvalidPointerPair(uptr a1, uptr a2) { + if (a1 == a2) + return false; + + // 256B in shadow memory can be iterated quite fast + static const uptr kMaxOffset = 2048; + + uptr left = a1 < a2 ? a1 : a2; + uptr right = a1 < a2 ? a2 : a1; + uptr offset = right - left; + if (offset <= kMaxOffset) + return __asan_region_is_poisoned(left, offset); + + AsanThread *t = GetCurrentThread(); + + // check whether left is a stack memory pointer + if (uptr shadow_offset1 = t->GetStackVariableShadowStart(left)) { + uptr shadow_offset2 = t->GetStackVariableShadowStart(right); + return shadow_offset2 == 0 || shadow_offset1 != shadow_offset2; + } + + // check whether left is a heap memory address + HeapAddressDescription hdesc1, hdesc2; + if (GetHeapAddressInformation(left, 0, &hdesc1) && + hdesc1.chunk_access.access_type == kAccessTypeInside) + return !GetHeapAddressInformation(right, 0, &hdesc2) || + hdesc2.chunk_access.access_type != kAccessTypeInside || + hdesc1.chunk_access.chunk_begin != hdesc2.chunk_access.chunk_begin; + + // check whether left is an address of a global variable + GlobalAddressDescription gdesc1, gdesc2; + if (GetGlobalAddressInformation(left, 0, &gdesc1)) + return !GetGlobalAddressInformation(right - 1, 0, &gdesc2) || + !gdesc1.PointsInsideTheSameVariable(gdesc2); + + if (t->GetStackVariableShadowStart(right) || + GetHeapAddressInformation(right, 0, &hdesc2) || + GetGlobalAddressInformation(right - 1, 0, &gdesc2)) + return true; + + // At this point we know nothing about both a1 and a2 addresses. + return false; +} + static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { if (!flags()->detect_invalid_pointer_pairs) return; uptr a1 = reinterpret_cast<uptr>(p1); uptr a2 = reinterpret_cast<uptr>(p2); - AsanChunkView chunk1 = FindHeapChunkByAddress(a1); - AsanChunkView chunk2 = FindHeapChunkByAddress(a2); - bool valid1 = chunk1.IsAllocated(); - bool valid2 = chunk2.IsAllocated(); - if (!valid1 || !valid2 || !chunk1.Eq(chunk2)) { + + if (IsInvalidPointerPair(a1, a2)) { GET_CALLER_PC_BP_SP; - return ReportInvalidPointerPair(pc, bp, sp, a1, a2); + ReportInvalidPointerPair(pc, bp, sp, a1, a2); } } // ----------------------- Mac-specific reports ----------------- {{{1 |