For allocation, the block size calculation is snapped to block bin sizes, but for reallocation it is not. So the tail_size calculation will be wrong if the block size is not one of the bin sizes.
To illustrate the problem: assume an allocation size of 32 bytes. heap_get_block_size will return 40 bytes. heap_allocate_block_lfh will round it up to 48 bytes. The tail_size is thus, 48 - 8 - 32 = 8 bytes. Later, HeapReAlloc is called to shrink it to 30 bytes. heap_get_block_size returns 40 bytes, heap_resize_block_lfh will not return STATUS_NO_MEMORY, because ROUND_SIZE(30) == 32, and 30 < 32. It will then calculate the tail_size based on the new block_size, which is 40 bytes. So the new tail_size becomes: 40 - 8 - 30 = 2 bytes. But block->block_size is still 48 bytes! So what it actually did is **growing** the block to 48 - 8 - 2 = 38 bytes from 32 bytes.
This commit fixes it by also rounding up the block_size to bin sizes in heap_resize_block_lfh.
* * *
This was discovered serendipitously by ASan, because the heap shadowing code I added for ASan didn't expect `heap_allocate_block_lfh` to enlarged the block, this mismatch triggered an ASan report.