scudo: Check for UAF in ring buffer before OOB in more distant blocks.

It's more likely that we have a UAF than an OOB in blocks that are
more than 1 block away from the fault address, so the UAF should
appear first in the error report.

Differential Revision: https://reviews.llvm.org/D102379

GitOrigin-RevId: 9567131d03650bbaa82251f173bd6959e04d471d
diff --git a/combined.h b/combined.h
index 70aeaa8..95fc8d9 100644
--- a/combined.h
+++ b/combined.h
@@ -927,12 +927,25 @@
 
     auto *Depot = reinterpret_cast<const StackDepot *>(DepotPtr);
     size_t NextErrorReport = 0;
+
+    // Check for OOB in the current block and the two surrounding blocks. Beyond
+    // that, UAF is more likely.
     if (extractTag(FaultAddr) != 0)
       getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
                          RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
-                         MemorySize);
+                         MemorySize, 0, 2);
+
+    // Check the ring buffer. For primary allocations this will only find UAF;
+    // for secondary allocations we can find either UAF or OOB.
     getRingBufferErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
                            RingBufferPtr);
+
+    // Check for OOB in the 28 blocks surrounding the 3 we checked earlier.
+    // Beyond that we are likely to hit false positives.
+    if (extractTag(FaultAddr) != 0)
+      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
+                         RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
+                         MemorySize, 2, 16);
   }
 
 private:
@@ -1247,7 +1260,8 @@
                                  const StackDepot *Depot,
                                  const char *RegionInfoPtr, const char *Memory,
                                  const char *MemoryTags, uintptr_t MemoryAddr,
-                                 size_t MemorySize) {
+                                 size_t MemorySize, size_t MinDistance,
+                                 size_t MaxDistance) {
     uptr UntaggedFaultAddr = untagPointer(FaultAddr);
     u8 FaultAddrTag = extractTag(FaultAddr);
     BlockInfo Info =
@@ -1308,12 +1322,10 @@
       return NextErrorReport == NumErrorReports;
     };
 
-    if (CheckOOB(Info.BlockBegin))
+    if (MinDistance == 0 && CheckOOB(Info.BlockBegin))
       return;
 
-    // Check for OOB in the 30 surrounding blocks. Beyond that we are likely to
-    // hit false positives.
-    for (int I = 1; I != 16; ++I)
+    for (size_t I = Max<size_t>(MinDistance, 1); I != MaxDistance; ++I)
       if (CheckOOB(Info.BlockBegin + I * Info.BlockSize) ||
           CheckOOB(Info.BlockBegin - I * Info.BlockSize))
         return;