Put all allocation functions into dispatch table.

Implement these new functions for all of the debug malloc types.

Fix a number of bugs in the debug malloc functions related to overflow
conditions.
Fix a bug in dlpvalloc due to an overflow condition.

Fix various other bugs in the debug malloc functions.

Add new tests for malloc functions.

Bug: 11225066

Change-Id: Idf50f389603e2157645565bc15cd9365eec2e9dd
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index aa7c072..2cc38cc 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -250,6 +250,33 @@
     return Malloc(malloc_usable_size)(mem);
 }
 
+extern "C" struct mallinfo fill_mallinfo() {
+  return Malloc(mallinfo)();
+}
+
+extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
+  if ((alignment & (alignment - 1)) != 0) {
+    return EINVAL;
+  }
+  int saved_errno = errno;
+  *memptr = fill_memalign(alignment, size);
+  errno = saved_errno;
+  return (*memptr != NULL) ? 0 : ENOMEM;
+}
+
+extern "C" void* fill_pvalloc(size_t bytes) {
+  size_t pagesize = sysconf(_SC_PAGESIZE);
+  size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+  if (size < bytes) { // Overflow
+    return NULL;
+  }
+  return fill_memalign(pagesize, size);
+}
+
+extern "C" void* fill_valloc(size_t size) {
+  return fill_memalign(sysconf(_SC_PAGESIZE), size);
+}
+
 // =============================================================================
 // malloc leak functions
 // =============================================================================
@@ -265,6 +292,7 @@
 
     size_t size = bytes + sizeof(AllocationEntry);
     if (size < bytes) { // Overflow.
+        errno = ENOMEM;
         return NULL;
     }
 
@@ -327,6 +355,7 @@
     // Fail on overflow - just to be safe even though this code runs only
     // within the debugging C library, not the production one.
     if (n_elements && SIZE_MAX / n_elements < elem_size) {
+        errno = ENOMEM;
         return NULL;
     }
     size_t size = n_elements * elem_size;
@@ -350,6 +379,7 @@
     } else if (header->guard != GUARD) {
         debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
                    header->guard, header->entry);
+        errno = ENOMEM;
         return NULL;
     }
 
@@ -358,8 +388,8 @@
         size_t oldSize = header->entry->size & ~SIZE_FLAG_MASK;
         size_t copySize = (oldSize <= bytes) ? oldSize : bytes;
         memcpy(newMem, oldMem, copySize);
+        leak_free(oldMem);
     }
-    leak_free(oldMem);
 
     return newMem;
 }
@@ -428,3 +458,30 @@
     }
     return 0;
 }
+
+extern "C" struct mallinfo leak_mallinfo() {
+  return Malloc(mallinfo)();
+}
+
+extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
+  if ((alignment & (alignment - 1)) != 0) {
+    return EINVAL;
+  }
+  int saved_errno = errno;
+  *memptr = leak_memalign(alignment, size);
+  errno = saved_errno;
+  return (*memptr != NULL) ? 0 : ENOMEM;
+}
+
+extern "C" void* leak_pvalloc(size_t bytes) {
+  size_t pagesize = sysconf(_SC_PAGESIZE);
+  size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+  if (size < bytes) { // Overflow
+    return NULL;
+  }
+  return leak_memalign(pagesize, size);
+}
+
+extern "C" void* leak_valloc(size_t size) {
+  return leak_memalign(sysconf(_SC_PAGESIZE), size);
+}