Infact it is 2.6.6 that is broken (sorry for the confusion).
This version attempts to extend the block forwards or backwards in
preference to allocating a completely new block. If the increase in
size is less then a factor of two then the resulting copy will overlap.
To give a bit more detail on this, the exact place the problem occurs
when it decides to extend the block backwards.
Imagine the most basic memcpy implementation:
while (size --)
*p2 ++ = * p1 ++;
This would be safe for going backwards. So would many memcpy
implementations which is probably why this bug has gone unnoticed for a
while.
Of course, if the block is extended forwards, no data needs to be copied
at all since the start address remains unchanged.