Add malloc_chunk command test

pull/1220/head
CptGibbon 3 years ago committed by Disconnect3d
parent 3be4559970
commit ef89d417d6

@ -0,0 +1,71 @@
/* For testing the malloc_chunk command.
*
* Move chunks into each bin type so that the test can run the malloc_chunk command on each different type of free chunk.
*/
#include <stdlib.h>
#define INTERNAL_SIZE_T size_t
#define SIZE_SZ (sizeof (INTERNAL_SIZE_T))
#define CHUNK_HDR_SZ (2 * SIZE_SZ)
#define mem2chunk(mem) ((void*)(mem) - CHUNK_HDR_SZ)
void break_here(void) {}
void* allocated_chunk = NULL;
void* tcache_chunk = NULL;
void* fast_chunk = NULL;
void* small_chunk = NULL;
void* large_chunk = NULL;
void* unsorted_chunk = NULL;
int main(void)
{
void* chunks[6] = {0};
// Request 8 fastbin-sized chunks, free these later to populate both the tcache (if present) and a fastbin.
for (int i=0; i<6; i++)
{
chunks[i] = malloc(0x18);
}
void* tcache_ = malloc(0x18);
void* fast = malloc(0x18);
void* remainder_me = malloc(0x418);
malloc(0x18);
void* large = malloc(0x418);
malloc(0x18);
void* unsorted = malloc(0x418);
malloc(0x18);
// Populate 0x200 smallbin & 0x400 largebin.
// Use remaindering to avoid tcache (if present).
free(remainder_me);
void* before_remainder = malloc(0x208);
free(large);
malloc(0x428);
// Populate the unsortedbin.
free(unsorted);
// Populate 0x20 tcachebin (if present) & fastbin.
for (int i=0; i<6; i++)
{
free(chunks[i]);
}
free(tcache_);
free(fast);
allocated_chunk = mem2chunk(remainder_me);
tcache_chunk = mem2chunk(tcache_);
fast_chunk = mem2chunk(fast);
small_chunk = mem2chunk(before_remainder + 0x210);
large_chunk = mem2chunk(large);
unsorted_chunk = mem2chunk(unsorted);
break_here();
}

@ -13,6 +13,7 @@ _, OUTPUT_FILE = tempfile.mkstemp()
HEAP_VIS = tests.binaries.get("heap_vis.out")
HEAP_FIND_FAKE_FAST = tests.binaries.get("heap_find_fake_fast.out")
HEAP_MALLOC_CHUNK = tests.binaries.get("heap_malloc_chunk.out")
def binary_parse_breakpoints(binary_code):
@ -415,3 +416,94 @@ def test_find_fake_fast_command(start_binary):
# A gdb.MemoryError raised here indicates a regression from PR #1145
gdb.execute("find_fake_fast (void*)&fake_chunk+0x70")
def test_malloc_chunk_command(start_binary):
start_binary(HEAP_MALLOC_CHUNK)
gdb.execute("break break_here")
gdb.execute("continue")
allocated_chunk = pwndbg.gdblib.memory.poi(
pwndbg.heap.current.malloc_chunk, gdb.lookup_symbol("allocated_chunk")[0].value()
)
tcache_chunk = pwndbg.gdblib.memory.poi(
pwndbg.heap.current.malloc_chunk, gdb.lookup_symbol("tcache_chunk")[0].value()
)
fast_chunk = pwndbg.gdblib.memory.poi(
pwndbg.heap.current.malloc_chunk, gdb.lookup_symbol("fast_chunk")[0].value()
)
small_chunk = pwndbg.gdblib.memory.poi(
pwndbg.heap.current.malloc_chunk, gdb.lookup_symbol("small_chunk")[0].value()
)
large_chunk = pwndbg.gdblib.memory.poi(
pwndbg.heap.current.malloc_chunk, gdb.lookup_symbol("large_chunk")[0].value()
)
unsorted_chunk = pwndbg.gdblib.memory.poi(
pwndbg.heap.current.malloc_chunk, gdb.lookup_symbol("unsorted_chunk")[0].value()
)
allocated_result = gdb.execute("malloc_chunk allocated_chunk", to_string=True).splitlines()
tcache_result = gdb.execute("malloc_chunk tcache_chunk", to_string=True).splitlines()
fast_result = gdb.execute("malloc_chunk fast_chunk", to_string=True).splitlines()
small_result = gdb.execute("malloc_chunk small_chunk", to_string=True).splitlines()
large_result = gdb.execute("malloc_chunk large_chunk", to_string=True).splitlines()
unsorted_result = gdb.execute("malloc_chunk unsorted_chunk", to_string=True).splitlines()
allocated_expected = [
"Allocated chunk | PREV_INUSE",
f"Addr: {allocated_chunk.address}",
f"Size: 0x{int(allocated_chunk['mchunk_size' if 'mchunk_size' in (f.name for f in allocated_chunk.type.fields()) else 'size']):02x}",
"",
]
tcache_expected = [
f"Free chunk ({'tcache' if pwndbg.heap.current.has_tcache else 'fastbins'}) | PREV_INUSE",
f"Addr: {tcache_chunk.address}",
f"Size: 0x{int(tcache_chunk['mchunk_size' if 'mchunk_size' in (f.name for f in tcache_chunk.type.fields()) else 'size']):02x}",
f"fd: 0x{int(tcache_chunk['fd']):02x}",
"",
]
fast_expected = [
"Free chunk (fastbins) | PREV_INUSE",
f"Addr: {fast_chunk.address}",
f"Size: 0x{int(fast_chunk['mchunk_size' if 'mchunk_size' in (f.name for f in fast_chunk.type.fields()) else 'size']):02x}",
f"fd: 0x{int(fast_chunk['fd']):02x}",
"",
]
small_expected = [
"Free chunk (smallbins) | PREV_INUSE",
f"Addr: {small_chunk.address}",
f"Size: 0x{int(small_chunk['mchunk_size' if 'mchunk_size' in (f.name for f in small_chunk.type.fields()) else 'size']):02x}",
f"fd: 0x{int(small_chunk['fd']):02x}",
f"bk: 0x{int(small_chunk['bk']):02x}",
"",
]
large_expected = [
"Free chunk (largebins) | PREV_INUSE",
f"Addr: {large_chunk.address}",
f"Size: 0x{int(large_chunk['mchunk_size' if 'mchunk_size' in (f.name for f in large_chunk.type.fields()) else 'size']):02x}",
f"fd: 0x{int(large_chunk['fd']):02x}",
f"bk: 0x{int(large_chunk['bk']):02x}",
f"fd_nextsize: 0x{int(large_chunk['fd_nextsize']):02x}",
f"bk_nextsize: 0x{int(large_chunk['bk_nextsize']):02x}",
"",
]
unsorted_expected = [
"Free chunk (unsortedbin) | PREV_INUSE",
f"Addr: {unsorted_chunk.address}",
f"Size: 0x{int(unsorted_chunk['mchunk_size' if 'mchunk_size' in (f.name for f in unsorted_chunk.type.fields()) else 'size']):02x}",
f"fd: 0x{int(unsorted_chunk['fd']):02x}",
f"bk: 0x{int(unsorted_chunk['bk']):02x}",
"",
]
assert allocated_result == allocated_expected
assert tcache_result == tcache_expected
assert fast_result == fast_expected
assert small_result == small_expected
assert large_result == large_expected
assert unsorted_result == unsorted_expected

Loading…
Cancel
Save