Log when malloc functions fail.
This shouldn't happen often, and resulting failures can be hard to debug.
From the bionic unit tests now:
W libc : malloc(18446744073709551615) failed: returning null pointer
W libc : calloc(18446744073709551615, 100) failed: returning null pointer
W libc : calloc(1, 18446744073709551615) failed: returning null pointer
W libc : calloc(18446744073709551615, 18446744073709551615) failed: returning null pointer
W libc : calloc(2, 18446744073709551615) failed: returning null pointer
W libc : calloc(18446744073709551615, 2) failed: returning null pointer
W libc : memalign(4096, 18446744073709551615) failed: returning null pointer
W libc : realloc(0x0, 18446744073709551615) failed: returning null pointer
W libc : realloc(0x75d7526070, 18446744073709551615) failed: returning null pointer
W libc : reallocaray(0x0, 9223372036854775812, 2) failed: returning null pointer
W libc : reallocaray(0x0, 2, 9223372036854775812) failed: returning null pointer
Bug: http://b/12821450
Test: ran tests
Change-Id: Ib176814404f4ba1297416dd3e1edd721bf59aeed
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 80e82f7..bb8ec59 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -69,7 +69,11 @@
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->calloc(n_elements, elem_size);
}
- return Malloc(calloc)(n_elements, elem_size);
+ void* result = Malloc(calloc)(n_elements, elem_size);
+ if (__predict_false(result == nullptr)) {
+ warning_log("calloc(%zu, %zu) failed: returning null pointer", n_elements, elem_size);
+ }
+ return result;
}
extern "C" void free(void* mem) {
@@ -102,7 +106,11 @@
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->malloc(bytes);
}
- return Malloc(malloc)(bytes);
+ void* result = Malloc(malloc)(bytes);
+ if (__predict_false(result == nullptr)) {
+ warning_log("malloc(%zu) failed: returning null pointer", bytes);
+ }
+ return result;
}
extern "C" size_t malloc_usable_size(const void* mem) {
@@ -118,7 +126,11 @@
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->memalign(alignment, bytes);
}
- return Malloc(memalign)(alignment, bytes);
+ void* result = Malloc(memalign)(alignment, bytes);
+ if (__predict_false(result == nullptr)) {
+ warning_log("memalign(%zu, %zu) failed: returning null pointer", alignment, bytes);
+ }
+ return result;
}
extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -134,7 +146,11 @@
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->aligned_alloc(alignment, size);
}
- return Malloc(aligned_alloc)(alignment, size);
+ void* result = Malloc(aligned_alloc)(alignment, size);
+ if (__predict_false(result == nullptr)) {
+ warning_log("aligned_alloc(%zu, %zu) failed: returning null pointer", alignment, size);
+ }
+ return result;
}
extern "C" void* realloc(void* old_mem, size_t bytes) {
@@ -142,12 +158,18 @@
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->realloc(old_mem, bytes);
}
- return Malloc(realloc)(old_mem, bytes);
+ void* result = Malloc(realloc)(old_mem, bytes);
+ if (__predict_false(result == nullptr && bytes != 0)) {
+ warning_log("realloc(%p, %zu) failed: returning null pointer", old_mem, bytes);
+ }
+ return result;
}
extern "C" void* reallocarray(void* old_mem, size_t item_count, size_t item_size) {
size_t new_size;
if (__builtin_mul_overflow(item_count, item_size, &new_size)) {
+ warning_log("reallocaray(%p, %zu, %zu) failed: returning null pointer",
+ old_mem, item_count, item_size);
errno = ENOMEM;
return nullptr;
}
@@ -160,7 +182,11 @@
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->pvalloc(bytes);
}
- return Malloc(pvalloc)(bytes);
+ void* result = Malloc(pvalloc)(bytes);
+ if (__predict_false(result == nullptr)) {
+ warning_log("pvalloc(%zu) failed: returning null pointer", bytes);
+ }
+ return result;
}
extern "C" void* valloc(size_t bytes) {
@@ -168,7 +194,11 @@
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->valloc(bytes);
}
- return Malloc(valloc)(bytes);
+ void* result = Malloc(valloc)(bytes);
+ if (__predict_false(result == nullptr)) {
+ warning_log("valloc(%zu) failed: returning null pointer", bytes);
+ }
+ return result;
}
#endif
// =============================================================================
diff --git a/libc/bionic/malloc_common.h b/libc/bionic/malloc_common.h
index a2f338a..e3326cf 100644
--- a/libc/bionic/malloc_common.h
+++ b/libc/bionic/malloc_common.h
@@ -71,4 +71,6 @@
async_safe_format_log(ANDROID_LOG_ERROR, "libc", (format), ##__VA_ARGS__ )
#define info_log(format, ...) \
async_safe_format_log(ANDROID_LOG_INFO, "libc", (format), ##__VA_ARGS__ )
+#define warning_log(format, ...) \
+ async_safe_format_log(ANDROID_LOG_WARN, "libc", (format), ##__VA_ARGS__ )
// =============================================================================