bionic_allocator: more detailed and consistent error reporting.
I only came to improve the signature mismatch error, but I was then annoyed by the copy & paste of the other checks.
get_chunk_size() seems to be deliberately avoiding any checks, though I think that might be a bug, and there should be a get_chunk_size() that _does_ check for most callers, and a get_chunk_size_unchecked() for the <sys/thread_properties.h> stuff that seems to want to only be "best effort" (but does still have _some_ possibility of aborting, in addition to the possibility of segfaulting).
Also a bit of "include what you use" after cider complained about all the unused includes in bionic_allocator.h.
Bug: https://issuetracker.google.com/341850283
Change-Id: I278b495601353733af516a2d60ed10feb9cef36b
diff --git a/libc/bionic/bionic_allocator.cpp b/libc/bionic/bionic_allocator.cpp
index 80e8b08..41baf8b 100644
--- a/libc/bionic/bionic_allocator.cpp
+++ b/libc/bionic/bionic_allocator.cpp
@@ -299,7 +299,7 @@
log2_size = kSmallObjectMinSizeLog2;
}
- return get_small_object_allocator(log2_size)->alloc();
+ return get_small_object_allocator_unchecked(log2_size)->alloc();
}
void* BionicAllocator::alloc(size_t size) {
@@ -330,9 +330,10 @@
inline page_info* BionicAllocator::get_page_info(void* ptr) {
page_info* info = get_page_info_unchecked(ptr);
if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) {
- async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
+ async_safe_fatal("invalid pointer %p (page signature %04x instead of %04x)", ptr,
+ *reinterpret_cast<const unsigned*>(info->signature),
+ *reinterpret_cast<const unsigned*>(kSignature));
}
-
return info;
}
@@ -353,12 +354,7 @@
if (info->type == kLargeObject) {
old_size = info->allocated_size - (static_cast<char*>(ptr) - reinterpret_cast<char*>(info));
} else {
- BionicSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
- if (allocator != info->allocator_addr) {
- async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
- }
-
- old_size = allocator->get_block_size();
+ old_size = get_small_object_allocator(info, ptr)->get_block_size();
}
if (old_size < size) {
@@ -377,16 +373,10 @@
}
page_info* info = get_page_info(ptr);
-
if (info->type == kLargeObject) {
munmap(info, info->allocated_size);
} else {
- BionicSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
- if (allocator != info->allocator_addr) {
- async_safe_fatal("invalid pointer %p (invalid allocator address for the page)", ptr);
- }
-
- allocator->free(ptr);
+ get_small_object_allocator(info, ptr)->free(ptr);
}
}
@@ -402,7 +392,7 @@
return info->allocated_size - (static_cast<char*>(ptr) - reinterpret_cast<char*>(info));
}
- BionicSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
+ BionicSmallObjectAllocator* allocator = get_small_object_allocator_unchecked(info->type);
if (allocator != info->allocator_addr) {
// Invalid pointer.
return 0;
@@ -410,7 +400,7 @@
return allocator->get_block_size();
}
-BionicSmallObjectAllocator* BionicAllocator::get_small_object_allocator(uint32_t type) {
+BionicSmallObjectAllocator* BionicAllocator::get_small_object_allocator_unchecked(uint32_t type) {
if (type < kSmallObjectMinSizeLog2 || type > kSmallObjectMaxSizeLog2) {
async_safe_fatal("invalid type: %u", type);
}
@@ -418,3 +408,11 @@
initialize_allocators();
return &allocators_[type - kSmallObjectMinSizeLog2];
}
+
+BionicSmallObjectAllocator* BionicAllocator::get_small_object_allocator(page_info* pi, void* ptr) {
+ BionicSmallObjectAllocator* result = get_small_object_allocator_unchecked(pi->type);
+ if (result != pi->allocator_addr) {
+ async_safe_fatal("invalid pointer %p (invalid allocator address for the page)", ptr);
+ }
+ return result;
+}
\ No newline at end of file