Partial-Message Collisions on Iterated Hash Functions
If you go through what Ferguson said, I'm sure he'll include a condition that $m$ and $m'$ are the same length, which is also a multiple of the hash block size. In this case, $m||X$ and $m'||X$ will not be preprocessed into single blocks; instead, they'll be processed as (at least) two blocks; one being $m$ (or $m'$), and the rest consisting only of $X$.

What's crucial is that the state of the hash function after processing $m$ and $m'$ are the same.  Because the state is the only way the hash function 'remembers' what came before, it'll do the same thing in both cases when processing $X$; hence $h(m || X) = h(m' || X)$