Fix nullptr dereference during sort.

Add new unit test that will crash without this fix.

Bug: 78900050

Test: Ran unit tests.
Change-Id: I73e1b89e965a7b399822c3a6f25cbc70d2d355e2
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index f811a5e..85139e6 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -392,10 +392,12 @@
     FrameInfoType* b_frame = b.frame_info;
     if (a_frame == nullptr && b_frame != nullptr) {
       return false;
-    }
-    if (a_frame != nullptr && b_frame == nullptr) {
+    } else if (a_frame != nullptr && b_frame == nullptr) {
       return true;
+    } else if (a_frame == nullptr && b_frame == nullptr) {
+      return a.pointer < b.pointer;
     }
+
     // Put the pointers with longest backtrace first.
     if (a_frame->frames.size() != b_frame->frames.size()) {
       return a_frame->frames.size() > b_frame->frames.size();
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 8b28188..1504d06 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -1756,6 +1756,53 @@
   ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugTest, backtrace_frame_data_nullptr_same_size) {
+  Init("backtrace=4");
+
+  size_t individual_size = GetInfoEntrySize(4);
+
+  void* pointers[4];
+  pointers[0] = debug_malloc(100);
+  ASSERT_TRUE(pointers[0] != nullptr);
+  pointers[1] = debug_malloc(100);
+  ASSERT_TRUE(pointers[1] != nullptr);
+  pointers[2] = debug_malloc(100);
+  ASSERT_TRUE(pointers[2] != nullptr);
+  pointers[3] = debug_malloc(100);
+  ASSERT_TRUE(pointers[3] != nullptr);
+
+  uint8_t* info;
+  size_t overall_size;
+  size_t info_size;
+  size_t total_memory;
+  size_t backtrace_size;
+
+  debug_get_malloc_leak_info(&info, &overall_size, &info_size, &total_memory, &backtrace_size);
+  ASSERT_TRUE(info != nullptr);
+  ASSERT_EQ(individual_size, overall_size);
+  EXPECT_EQ(individual_size, info_size);
+  EXPECT_EQ(400U, total_memory);
+  EXPECT_EQ(4U, backtrace_size);
+
+  EXPECT_EQ(100U, *reinterpret_cast<size_t*>(&info[0]));
+  EXPECT_EQ(4U, *reinterpret_cast<size_t*>(&info[sizeof(size_t)]));
+  uintptr_t* ips = reinterpret_cast<uintptr_t*>(&info[2 * sizeof(size_t)]);
+  EXPECT_EQ(0U, ips[0]);
+
+  debug_free_malloc_leak_info(info);
+
+  debug_free(pointers[0]);
+  debug_free(pointers[1]);
+  debug_free(pointers[2]);
+  debug_free(pointers[3]);
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string expected_log = android::base::StringPrintf(
+      "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n",
+      SIGRTMAX - 17, getpid());
+  ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
 TEST_F(MallocDebugTest, overflow) {
   Init("guard fill_on_free");