Memory corruption bugs are usually very hard to find because they often lead to a program crash in a source line far from the point of the actual bug. Buffer overruns are an important reason for memory corruption. Libcwd tries to help with finding buffer overruns by means of so called magic numbers.
When --enable-magic (CWDEBUG_MAGIC) is defined, magic numbers are added to the beginning and the end of each allocated memory block. In addition to these two magic numbers, extra memory is allocated to hold the allocated size, this is necessary to find back the location of the magic number at the end with only a pointer to the beginning of the allocated memory block. The total size of actually allocated memory is therefore larger than was requested. The size of each field is equal to the size of a
size_t. Moreover, a few bytes might be allocated extra just in front of the last magic number in order to word align this number.
malloc etc. return a pointer just beyond this size field, see figure 1.
Figure 1. Memory layout of an allocated memory block with
The magic numbers are checked when the memory is freed again. Libcwd uses twelve different magic numbers for six pairs, existing each of a start magic number and an end magic number. The six pairs consist of two groups: for memory allocated by the user and for memory allocated internally by libcwd as part of the debug malloc code itself. Thus, each group consists of three pairs: for memory allocated with
operator new and
operator new respectively.
For example, the following code snippet:
int* p = new int; AllocTag(p, "Test array"); Debug( list_allocations_on(libcw_do) ); p = 5; // Buffer overflow delete p;
results in output like
MALLOC : operator new (size = 16) = 0x8116460
MALLOC : Allocated memory: 16 bytes in 1 blocks. new 0x8116460 magic_tst.cc:174 int ; (sz = 16) Test array
MALLOC : delete 0x8116460 magic_tst.cc:174 int ; (sz = 16) Test array <unfinished> COREDUMP: delete: magic number corrupt! Quit (core dumped)