Merge "Mangle the pointers stored in PointerData."
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index b982c0a..eaa0eb7 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <functional>
 #include <mutex>
 #include <string>
 #include <unordered_map>
@@ -195,40 +196,41 @@
 }
 
 void PointerData::Add(const void* ptr, size_t pointer_size) {
-  uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
   size_t hash_index = 0;
   if (backtrace_enabled_) {
     hash_index = AddBacktrace(g_debug->config().backtrace_frames());
   }
 
   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
-  pointers_[pointer] = PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index};
+  uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+  pointers_[mangled_ptr] =
+      PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index};
 }
 
 void PointerData::Remove(const void* ptr) {
-  uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
   size_t hash_index;
   {
     std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
-    auto entry = pointers_.find(pointer);
+    uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+    auto entry = pointers_.find(mangled_ptr);
     if (entry == pointers_.end()) {
       // Attempt to remove unknown pointer.
-      error_log("No tracked pointer found for 0x%" PRIxPTR, pointer);
+      error_log("No tracked pointer found for 0x%" PRIxPTR, DemanglePointer(mangled_ptr));
       return;
     }
     hash_index = entry->second.hash_index;
-    pointers_.erase(pointer);
+    pointers_.erase(mangled_ptr);
   }
 
   RemoveBacktrace(hash_index);
 }
 
 size_t PointerData::GetFrames(const void* ptr, uintptr_t* frames, size_t max_frames) {
-  uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
   size_t hash_index;
   {
     std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
-    auto entry = pointers_.find(pointer);
+    uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+    auto entry = pointers_.find(mangled_ptr);
     if (entry == pointers_.end()) {
       return 0;
     }
@@ -274,7 +276,8 @@
 
 void PointerData::LogFreeError(const FreePointerInfoType& info, size_t max_cmp_bytes) {
   error_log(LOG_DIVIDER);
-  uint8_t* memory = reinterpret_cast<uint8_t*>(info.pointer);
+  uintptr_t pointer = DemanglePointer(info.mangled_ptr);
+  uint8_t* memory = reinterpret_cast<uint8_t*>(pointer);
   error_log("+++ ALLOCATION %p USED AFTER FREE", memory);
   uint8_t fill_free_value = g_debug->config().fill_free_value();
   for (size_t i = 0; i < max_cmp_bytes; i++) {
@@ -296,13 +299,14 @@
 
 void PointerData::VerifyFreedPointer(const FreePointerInfoType& info) {
   size_t usable_size;
+  uintptr_t pointer = DemanglePointer(info.mangled_ptr);
   if (g_debug->HeaderEnabled()) {
     // Check to see if the tag data has been damaged.
-    Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(info.pointer));
+    Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(pointer));
     if (header->tag != DEBUG_FREE_TAG) {
       error_log(LOG_DIVIDER);
-      error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE",
-                info.pointer, header->tag);
+      error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", pointer,
+                header->tag);
       error_log(LOG_DIVIDER);
       if (g_debug->config().options() & ABORT_ON_ERROR) {
         abort();
@@ -314,14 +318,14 @@
     }
     usable_size = header->usable_size;
   } else {
-    usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(info.pointer));
+    usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(pointer));
   }
 
   size_t bytes = (usable_size < g_debug->config().fill_on_free_bytes())
                      ? usable_size
                      : g_debug->config().fill_on_free_bytes();
   size_t max_cmp_bytes = bytes;
-  const uint8_t* memory = reinterpret_cast<const uint8_t*>(info.pointer);
+  const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
   while (bytes > 0) {
     size_t bytes_to_cmp = (bytes < g_cmp_mem.size()) ? bytes : g_cmp_mem.size();
     if (memcmp(memory, g_cmp_mem.data(), bytes_to_cmp) != 0) {
@@ -333,8 +337,6 @@
 }
 
 void* PointerData::AddFreed(const void* ptr) {
-  uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
-
   size_t hash_index = 0;
   size_t num_frames = g_debug->config().free_track_backtrace_num_frames();
   if (num_frames) {
@@ -348,10 +350,11 @@
     free_pointers_.pop_front();
     VerifyFreedPointer(info);
     RemoveBacktrace(info.hash_index);
-    last = reinterpret_cast<void*>(info.pointer);
+    last = reinterpret_cast<void*>(DemanglePointer(info.mangled_ptr));
   }
 
-  free_pointers_.emplace_back(FreePointerInfoType{pointer, hash_index});
+  uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+  free_pointers_.emplace_back(FreePointerInfoType{mangled_ptr, hash_index});
   return last;
 }
 
@@ -361,7 +364,7 @@
     uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
     std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_);
     for (const auto& info : free_pointers_) {
-      if (info.pointer == pointer) {
+      if (DemanglePointer(info.mangled_ptr) == pointer) {
         hash_index = info.hash_index;
         break;
       }
@@ -388,6 +391,7 @@
   for (const auto& entry : pointers_) {
     FrameInfoType* frame_info = nullptr;
     std::vector<unwindstack::FrameData>* backtrace_info = nullptr;
+    uintptr_t pointer = DemanglePointer(entry.first);
     size_t hash_index = entry.second.hash_index;
     if (hash_index > kBacktraceEmptyIndex) {
       auto frame_entry = frames_.find(hash_index);
@@ -397,7 +401,7 @@
         // occurs after the hash_index and frame data have been added.
         // When removing a pointer, the pointer is deleted before the frame
         // data.
-        error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+        error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
       } else {
         frame_info = &frame_entry->second;
       }
@@ -405,7 +409,7 @@
       if (g_debug->config().options() & BACKTRACE_FULL) {
         auto backtrace_entry = backtraces_info_.find(hash_index);
         if (backtrace_entry == backtraces_info_.end()) {
-          error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+          error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
         } else {
           backtrace_info = &backtrace_entry->second;
         }
@@ -415,7 +419,7 @@
       continue;
     }
 
-    list->emplace_back(ListInfoType{entry.first, 1, entry.second.RealSize(),
+    list->emplace_back(ListInfoType{pointer, 1, entry.second.RealSize(),
                                     entry.second.ZygoteChildAlloc(), frame_info, backtrace_info});
   }
 
@@ -550,9 +554,9 @@
 }
 
 bool PointerData::Exists(const void* ptr) {
-  uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
-  return pointers_.count(pointer) != 0;
+  uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+  return pointers_.count(mangled_ptr) != 0;
 }
 
 void PointerData::DumpLiveToFile(int fd) {
@@ -637,3 +641,10 @@
   free_pointer_mutex_.try_lock();
   free_pointer_mutex_.unlock();
 }
+
+void PointerData::IteratePointers(std::function<void(uintptr_t pointer)> fn) {
+  std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
+  for (const auto entry : pointers_) {
+    fn(DemanglePointer(entry.first));
+  }
+}
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 92d2653..97eec0a 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -33,6 +33,7 @@
 
 #include <atomic>
 #include <deque>
+#include <functional>
 #include <mutex>
 #include <string>
 #include <unordered_map>
@@ -99,7 +100,7 @@
 };
 
 struct FreePointerInfoType {
-  uintptr_t pointer;
+  uintptr_t mangled_ptr;
   size_t hash_index;
 };
 
@@ -134,16 +135,14 @@
   void PostForkParent();
   void PostForkChild();
 
+  static void IteratePointers(std::function<void(uintptr_t pointer)> fn);
+
   static size_t AddBacktrace(size_t num_frames);
   static void RemoveBacktrace(size_t hash_index);
 
   static void Add(const void* pointer, size_t size);
   static void Remove(const void* pointer);
 
-  typedef std::unordered_map<uintptr_t, PointerInfoType>::iterator iterator;
-  static iterator begin() { return pointers_.begin(); }
-  static iterator end() { return pointers_.end(); }
-
   static void* AddFreed(const void* pointer);
   static void LogFreeError(const FreePointerInfoType& info, size_t usable_size);
   static void LogFreeBacktrace(const void* ptr);
@@ -162,6 +161,12 @@
   static bool Exists(const void* pointer);
 
  private:
+  // Only keep mangled pointers in internal data structures. This avoids
+  // problems where libmemunreachable finds these pointers and thinks they
+  // are not unreachable.
+  static inline uintptr_t ManglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; }
+  static inline uintptr_t DemanglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; }
+
   static std::string GetHashString(uintptr_t* frames, size_t num_frames);
   static void LogBacktrace(size_t hash_index);
 
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 9f38946..d608f5d 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -890,10 +890,9 @@
                   void* arg) {
   ScopedConcurrentLock lock;
   if (g_debug->TrackPointers()) {
-    // Since malloc is disabled, don't bother acquiring any locks.
-    for (auto it = PointerData::begin(); it != PointerData::end(); ++it) {
-      callback(it->first, InternalMallocUsableSize(reinterpret_cast<void*>(it->first)), arg);
-    }
+    PointerData::IteratePointers([&callback, &arg](uintptr_t pointer) {
+      callback(pointer, InternalMallocUsableSize(reinterpret_cast<void*>(pointer)), arg);
+    });
     return 0;
   }