malloc debug: fix LogFreeError error log
When free_track option is enabled and malloc debug detects error in
VerifyFreedPointer flow, if freed pointer's usable_size is more than
g_debug->config().fill_on_free_bytes(), the error log is not correct.
The max. bytes printed to error message should be the max bytes to
cmp, not usable size.
Bug: 124420174
Test: build pass and test pass
Change-Id: I41f35ab3330e49e0a6ad276d405bf4f6c3f0ea92
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index 638061b..6e9d24f 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -266,12 +266,12 @@
error_log(" hash_index %zu does not have matching frame data.", hash_index);
}
-void PointerData::LogFreeError(const FreePointerInfoType& info, size_t usable_size) {
+void PointerData::LogFreeError(const FreePointerInfoType& info, size_t max_cmp_bytes) {
error_log(LOG_DIVIDER);
uint8_t* memory = reinterpret_cast<uint8_t*>(info.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 < usable_size; i++) {
+ for (size_t i = 0; i < max_cmp_bytes; i++) {
if (memory[i] != fill_free_value) {
error_log(" allocation[%zu] = 0x%02x (expected 0x%02x)", i, memory[i], fill_free_value);
}
@@ -314,11 +314,12 @@
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);
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) {
- LogFreeError(info, usable_size);
+ LogFreeError(info, max_cmp_bytes);
}
bytes -= bytes_to_cmp;
memory = &memory[bytes_to_cmp];
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 44f9795..6da95ca 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -990,6 +990,35 @@
ASSERT_STREQ("", getFakeLogPrint().c_str());
}
+TEST_F(MallocDebugTest, free_track_pointer_modified_after_free) {
+ Init("free_track=4 fill_on_free=2 free_track_backtrace_num_frames=0");
+
+ void* pointers[5];
+ for (size_t i = 0; i < sizeof(pointers) / sizeof(void*); i++) {
+ pointers[i] = debug_malloc(100);
+ ASSERT_TRUE(pointers[i] != nullptr);
+ memset(pointers[i], 0, 100);
+ }
+
+ debug_free(pointers[0]);
+
+ // overwrite the whole pointer, only expect errors on the fill bytes we check.
+ memset(pointers[0], 0x20, 100);
+
+ for (size_t i = 1; i < sizeof(pointers) / sizeof(void*); i++) {
+ debug_free(pointers[i]);
+ }
+
+ std::string expected_log(DIVIDER);
+ expected_log += android::base::StringPrintf("6 malloc_debug +++ ALLOCATION %p USED AFTER FREE\n",
+ pointers[0]);
+ expected_log += "6 malloc_debug allocation[0] = 0x20 (expected 0xef)\n";
+ expected_log += "6 malloc_debug allocation[1] = 0x20 (expected 0xef)\n";
+ expected_log += DIVIDER;
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
TEST_F(MallocDebugTest, get_malloc_leak_info_invalid) {
Init("fill");