Holy cow, I wrote a book!
This time, I'm
not going to set up a story.
I'm just going to go straight to the punch line.
A customer overrode the new operator in order to add
Something like this:
// error checking elided for expository purposes
void *operator new(size_t n)
EXTRASTUFF *extra = (EXTRASTUFF)malloc(sizeof(EXTRASTUFF) + n);
extra->Awesome1 = get_awesome_1();
extra->Awesome2 = get_awesome_2();
return ((BYTE *)extra) + sizeof(EXTRASTUFF);
// use your imagination to implement
// operators new, delete, and delete
This worked out okay on 32-bit systems because in 32-bit Windows,
MEMORY_ALLOCATION_ALIGNMENT is 8,
and sizeof(EXTRASTUFF) is also 8.
If you start with a value that is a multiple of 8,
then add 8 to it,
the result is still a multiple of 8,
so the pointer returned by the custom
operator new remains properly aligned.
But on 64-bit systems, things went awry.
On 64-bit systems,
MEMORY_ALLOCATION_ALIGNMENT is 16,
As a result, the custom
operator new handed out guaranteed-misaligned memory.
The misalignment went undetected for a long time,
but the sleeping bug finally woke up when somebody
allocated a structure that contained an
As we saw earlier,
really does need to be aligned according to the
especially on 64-bit systems,
because 64-bit Windows takes advantage of the extra "guaranteed to be zero"
bits that 16-byte alignment gives you.
SLIST_ENTRY is not 16-byte aligned,
then those "guaranteed to be zero" bits are not actually zero,
and then the algorithm breaks down.
Result: Memory corruption and eventually a crash.