|
|
fa3bfd |
From 265cbed8e73b23e3b38ada6cc42482c53a216224 Mon Sep 17 00:00:00 2001
|
|
|
fa3bfd |
From: James Lemke <jwlemke@codesourcery.com>
|
|
|
fa3bfd |
Date: Tue, 19 May 2015 12:10:26 -0700
|
|
|
fa3bfd |
Subject: [PATCH] Fix for test "malloc_usable_size: expected 7 but got 11"
|
|
|
fa3bfd |
|
|
|
fa3bfd |
[BZ #17581] The checking chain of unused chunks was terminated by a hash of
|
|
|
fa3bfd |
the block pointer, which was sometimes confused with the chunk length byte.
|
|
|
fa3bfd |
We now avoid using a length byte equal to the magic byte.
|
|
|
fa3bfd |
|
|
|
fa3bfd |
|
|
|
fa3bfd |
diff -rup a/malloc/hooks.c b/malloc/hooks.c
|
|
|
fa3bfd |
--- a/malloc/hooks.c 2017-08-01 16:19:28.000000000 -0400
|
|
|
fa3bfd |
+++ b/malloc/hooks.c 2017-08-01 16:42:23.651295223 -0400
|
|
|
fa3bfd |
@@ -87,11 +87,22 @@ __malloc_check_init()
|
|
|
fa3bfd |
overruns. The goal here is to avoid obscure crashes due to invalid
|
|
|
fa3bfd |
usage, unlike in the MALLOC_DEBUG code. */
|
|
|
fa3bfd |
|
|
|
fa3bfd |
-#define MAGICBYTE(p) ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )
|
|
|
fa3bfd |
+static unsigned char
|
|
|
fa3bfd |
+magicbyte (const void *p)
|
|
|
fa3bfd |
+{
|
|
|
fa3bfd |
+ unsigned char magic;
|
|
|
fa3bfd |
+
|
|
|
fa3bfd |
+ magic = (((uintptr_t) p >> 3) ^ ((uintptr_t) p >> 11)) & 0xFF;
|
|
|
fa3bfd |
+ /* Do not return 1. See the comment in mem2mem_check(). */
|
|
|
fa3bfd |
+ if (magic == 1)
|
|
|
fa3bfd |
+ ++magic;
|
|
|
fa3bfd |
+ return magic;
|
|
|
fa3bfd |
+}
|
|
|
fa3bfd |
+
|
|
|
fa3bfd |
|
|
|
fa3bfd |
-/* Visualize the chunk as being partitioned into blocks of 256 bytes from the
|
|
|
fa3bfd |
- highest address of the chunk, downwards. The beginning of each block tells
|
|
|
fa3bfd |
- us the size of the previous block, up to the actual size of the requested
|
|
|
fa3bfd |
+/* Visualize the chunk as being partitioned into blocks of 255 bytes from the
|
|
|
fa3bfd |
+ highest address of the chunk, downwards. The end of each block tells
|
|
|
fa3bfd |
+ us the size of that block, up to the actual size of the requested
|
|
|
fa3bfd |
memory. Our magic byte is right at the end of the requested size, so we
|
|
|
fa3bfd |
must reach it with this iteration, otherwise we have witnessed a memory
|
|
|
fa3bfd |
corruption. */
|
|
|
fa3bfd |
@@ -100,7 +111,7 @@ malloc_check_get_size(mchunkptr p)
|
|
|
fa3bfd |
{
|
|
|
fa3bfd |
size_t size;
|
|
|
fa3bfd |
unsigned char c;
|
|
|
fa3bfd |
- unsigned char magic = MAGICBYTE(p);
|
|
|
fa3bfd |
+ unsigned char magic = magicbyte (p);
|
|
|
fa3bfd |
|
|
|
fa3bfd |
assert(using_malloc_checking == 1);
|
|
|
fa3bfd |
|
|
|
fa3bfd |
@@ -120,29 +131,35 @@ malloc_check_get_size(mchunkptr p)
|
|
|
fa3bfd |
}
|
|
|
fa3bfd |
|
|
|
fa3bfd |
/* Instrument a chunk with overrun detector byte(s) and convert it
|
|
|
fa3bfd |
- into a user pointer with requested size sz. */
|
|
|
fa3bfd |
+ into a user pointer with requested size req_sz. */
|
|
|
fa3bfd |
|
|
|
fa3bfd |
static void*
|
|
|
fa3bfd |
internal_function
|
|
|
fa3bfd |
-mem2mem_check(void *ptr, size_t sz)
|
|
|
fa3bfd |
+mem2mem_check(void *ptr, size_t req_sz)
|
|
|
fa3bfd |
{
|
|
|
fa3bfd |
mchunkptr p;
|
|
|
fa3bfd |
unsigned char* m_ptr = ptr;
|
|
|
fa3bfd |
- size_t i;
|
|
|
fa3bfd |
+ size_t max_sz, block_sz, i;
|
|
|
fa3bfd |
+ unsigned char magic;
|
|
|
fa3bfd |
|
|
|
fa3bfd |
if (!ptr)
|
|
|
fa3bfd |
return ptr;
|
|
|
fa3bfd |
p = mem2chunk(ptr);
|
|
|
fa3bfd |
- for(i = chunksize(p) - (chunk_is_mmapped(p) ? 2*SIZE_SZ+1 : SIZE_SZ+1);
|
|
|
fa3bfd |
- i > sz;
|
|
|
fa3bfd |
- i -= 0xFF) {
|
|
|
fa3bfd |
- if(i-sz < 0x100) {
|
|
|
fa3bfd |
- m_ptr[i] = (unsigned char)(i-sz);
|
|
|
fa3bfd |
- break;
|
|
|
fa3bfd |
+ magic = magicbyte (p);
|
|
|
fa3bfd |
+ max_sz = chunksize (p) - 2 * SIZE_SZ;
|
|
|
fa3bfd |
+ if (!chunk_is_mmapped (p))
|
|
|
fa3bfd |
+ max_sz += SIZE_SZ;
|
|
|
fa3bfd |
+ for (i = max_sz - 1; i > req_sz; i -= block_sz)
|
|
|
fa3bfd |
+ {
|
|
|
fa3bfd |
+ block_sz = MIN (i - req_sz, 0xff);
|
|
|
fa3bfd |
+ /* Don't allow the magic byte to appear in the chain of length bytes.
|
|
|
fa3bfd |
+ For the following to work, magicbyte cannot return 0x01. */
|
|
|
fa3bfd |
+ if (block_sz == magic)
|
|
|
fa3bfd |
+ --block_sz;
|
|
|
fa3bfd |
+
|
|
|
fa3bfd |
+ m_ptr[i] = block_sz;
|
|
|
fa3bfd |
}
|
|
|
fa3bfd |
- m_ptr[i] = 0xFF;
|
|
|
fa3bfd |
- }
|
|
|
fa3bfd |
- m_ptr[sz] = MAGICBYTE(p);
|
|
|
fa3bfd |
+ m_ptr[req_sz] = magic;
|
|
|
fa3bfd |
return (void*)m_ptr;
|
|
|
fa3bfd |
}
|
|
|
fa3bfd |
|
|
|
fa3bfd |
@@ -159,10 +176,11 @@ mem2chunk_check(void* mem, unsigned char
|
|
|
fa3bfd |
|
|
|
fa3bfd |
if(!aligned_OK(mem)) return NULL;
|
|
|
fa3bfd |
p = mem2chunk(mem);
|
|
|
fa3bfd |
+ sz = chunksize (p);
|
|
|
fa3bfd |
+ magic = magicbyte (p);
|
|
|
fa3bfd |
if (!chunk_is_mmapped(p)) {
|
|
|
fa3bfd |
/* Must be a chunk in conventional heap memory. */
|
|
|
fa3bfd |
int contig = contiguous(&main_arena);
|
|
|
fa3bfd |
- sz = chunksize(p);
|
|
|
fa3bfd |
if((contig &&
|
|
|
fa3bfd |
((char*)p
|
|
|
fa3bfd |
((char*)p + sz)>=(mp_.sbrk_base+main_arena.system_mem) )) ||
|
|
|
fa3bfd |
@@ -171,9 +189,9 @@ mem2chunk_check(void* mem, unsigned char
|
|
|
fa3bfd |
(contig && (char*)prev_chunk(p)
|
|
|
fa3bfd |
next_chunk(prev_chunk(p))!=p) ))
|
|
|
fa3bfd |
return NULL;
|
|
|
fa3bfd |
- magic = MAGICBYTE(p);
|
|
|
fa3bfd |
for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
|
|
|
fa3bfd |
- if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
|
|
|
fa3bfd |
+ if(c == 0 || sz < (c + 2 * SIZE_SZ))
|
|
|
fa3bfd |
+ return NULL;
|
|
|
fa3bfd |
}
|
|
|
fa3bfd |
} else {
|
|
|
fa3bfd |
unsigned long offset, page_mask = GLRO(dl_pagesize)-1;
|
|
|
fa3bfd |
@@ -188,11 +206,12 @@ mem2chunk_check(void* mem, unsigned char
|
|
|
fa3bfd |
offset<0x2000) ||
|
|
|
fa3bfd |
!chunk_is_mmapped(p) || (p->size & PREV_INUSE) ||
|
|
|
fa3bfd |
( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) ||
|
|
|
fa3bfd |
- ( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) )
|
|
|
fa3bfd |
+ ((p->prev_size + sz) & page_mask) != 0)
|
|
|
fa3bfd |
return NULL;
|
|
|
fa3bfd |
- magic = MAGICBYTE(p);
|
|
|
fa3bfd |
+
|
|
|
fa3bfd |
for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
|
|
|
fa3bfd |
- if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
|
|
|
fa3bfd |
+ if(c == 0 || sz < (c + 2 * SIZE_SZ))
|
|
|
fa3bfd |
+ return NULL;
|
|
|
fa3bfd |
}
|
|
|
fa3bfd |
}
|
|
|
fa3bfd |
((unsigned char*)p)[sz] ^= 0xFF;
|