summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2010-08-09 13:43:46 -0700
committerChristopher Tate <ctate@google.com>2010-08-09 13:43:46 -0700
commit52e7d3d91ab6a5bab77c5dfb1ed47381fd52f9ba (patch)
tree95fd304d94292f13851cd4590e89a0b6acb3a297
parent18c5bcc66a9a7b2178dcdcf04a0716958798ab81 (diff)
downloadbionic-52e7d3d91ab6a5bab77c5dfb1ed47381fd52f9ba.zip
bionic-52e7d3d91ab6a5bab77c5dfb1ed47381fd52f9ba.tar.gz
bionic-52e7d3d91ab6a5bab77c5dfb1ed47381fd52f9ba.tar.bz2
Bulletproof leak dump against null hash entries
Previously, the malloc leak checking code would crash in qsort() if null entries existed in its bookkeeping table. This change makes the comparison function detect null entries and sort them to the end safely. Change-Id: I88244a7df1e289dd9d7992ce29606d505bd63079
-rw-r--r--libc/bionic/malloc_debug_common.c49
1 files changed, 29 insertions, 20 deletions
diff --git a/libc/bionic/malloc_debug_common.c b/libc/bionic/malloc_debug_common.c
index ec56826..f05576c 100644
--- a/libc/bionic/malloc_debug_common.c
+++ b/libc/bionic/malloc_debug_common.c
@@ -60,34 +60,43 @@ HashTable gHashTable;
static int hash_entry_compare(const void* arg1, const void* arg2)
{
+ int result;
+
HashEntry* e1 = *(HashEntry**)arg1;
HashEntry* e2 = *(HashEntry**)arg2;
- size_t nbAlloc1 = e1->allocations;
- size_t nbAlloc2 = e2->allocations;
- size_t size1 = e1->size & ~SIZE_FLAG_MASK;
- size_t size2 = e2->size & ~SIZE_FLAG_MASK;
- size_t alloc1 = nbAlloc1 * size1;
- size_t alloc2 = nbAlloc2 * size2;
-
- // sort in descending order by:
- // 1) total size
- // 2) number of allocations
- //
- // This is used for sorting, not determination of equality, so we don't
- // need to compare the bit flags.
- int result;
- if (alloc1 > alloc2) {
+ // if one or both arg pointers are null, deal gracefully
+ if (e1 == NULL) {
+ result = (e2 == NULL) ? 0 : 1;
+ } else if (e2 == NULL) {
result = -1;
- } else if (alloc1 < alloc2) {
- result = 1;
} else {
- if (nbAlloc1 > nbAlloc2) {
+ size_t nbAlloc1 = e1->allocations;
+ size_t nbAlloc2 = e2->allocations;
+ size_t size1 = e1->size & ~SIZE_FLAG_MASK;
+ size_t size2 = e2->size & ~SIZE_FLAG_MASK;
+ size_t alloc1 = nbAlloc1 * size1;
+ size_t alloc2 = nbAlloc2 * size2;
+
+ // sort in descending order by:
+ // 1) total size
+ // 2) number of allocations
+ //
+ // This is used for sorting, not determination of equality, so we don't
+ // need to compare the bit flags.
+ int result;
+ if (alloc1 > alloc2) {
result = -1;
- } else if (nbAlloc1 < nbAlloc2) {
+ } else if (alloc1 < alloc2) {
result = 1;
} else {
- result = 0;
+ if (nbAlloc1 > nbAlloc2) {
+ result = -1;
+ } else if (nbAlloc1 < nbAlloc2) {
+ result = 1;
+ } else {
+ result = 0;
+ }
}
}
return result;