[compiler-rt] [hwasan] Fix stack tag mismatch report (PR #81939)

Thurston Dang via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 15 15:55:43 PST 2024


================
@@ -230,33 +230,70 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
       tag_t obj_tag = base_tag ^ local.tag_offset;
       if (obj_tag != addr_tag)
         continue;
-      // Guess top bits of local variable from the faulting address, because
-      // we only store bits 4-19 of FP (bits 0-3 are guaranteed to be zero).
-      uptr local_beg = (fp + local.frame_offset) |
-                       (untagged_addr & ~(uptr(kRecordFPModulus) - 1));
-      uptr local_end = local_beg + local.size;
+
+      // We only store bits 4-19 of FP (bits 0-3 are guaranteed to be zero).
+      // So we know only `FP % kRecordFPModulus`, and we can only calculate
+      // `local_beg % kRecordFPModulus`.
+      // Out of all possible `local_beg` we will only consider two candidates
+      // nearest to the `untagged_addr`.
+      uptr local_beg_mod = (fp + local.frame_offset) % kRecordFPModulus;
+      // Pick `local_beg` in the same 1 MiB block as `untagged_addr`.
+      uptr local_beg =
+          RoundDownTo(untagged_addr, kRecordFPModulus) + local_beg_mod;
+      // Pick the largest `local_beg <= untagged_addr`. It's either the current
+      // one or the one before.
+      if (local_beg > untagged_addr)
+        local_beg -= kRecordFPModulus;
+
+      uptr offset = -1ull;
+      const char *whence;
+      const char *cause = nullptr;
+      uptr best_beg;
+
+      // Try two 1 MiB blocks options and pick nearest one.
+      for (uptr i = 0; i < 2; ++i, local_beg += kRecordFPModulus) {
+        uptr local_end = local_beg + local.size;
+        if (local_beg > local_end)
+          continue;  // This is a wraparound.
+        if (local_beg <= untagged_addr && untagged_addr < local_end) {
----------------
thurstond wrote:

The three if statements (`(local_beg <= untagged_addr && untagged_addr < local_end)`, `(untagged_addr >= local_end)`, `(untagged_addr < local_beg)`) seem mutually exclusive to me. If that is the case, would it be better to use 'if/else if' to make it clear to readers (and negligibly faster)?

https://github.com/llvm/llvm-project/pull/81939


More information about the llvm-commits mailing list