Allocating memory doesn't really do much to it except for (typically) writing some bookkeeping information into its header - a portion the caller doesn't (isn't supposed to...) see. In particular, that bit of memory doesn't become unavailable for anything (other than further allocation).
Malloc maintains a buffer between the stack pointer location and the heap, from which it will not allocate. This tends to ( <--- note "weasel words") prevent a heap vs. stack collision
If the stack grows down into memory that was already allocated, the stack will over-write the data in some allocated block. It is impossible to say what effect that will have on further program operation without knowing a whole lot more about the program, and quite possibly, about the contents and timing of any data that has yet to be received.
If the heap grows upward into the stack, and program writes into that allocated block, it will be over-writing parts of it's own stack with, again, unpredictable (without a lot more information) results.
A simple test program that merely allocates lots of small blocks will have a good chance of running forever, or at least until the
malloc() call returns a NULL pointer when it is out of memory to allocate. At that point, if the test program is checking for the NULL return, there is a good chance the program can print its message and end normally. But if the program blindly writes into the memory
malloc() returns, and writes through the eventual NULL pointer, then low-memory will get corrupted. Low memory is typically the location of the interrupt vector table (and the Arduinos' AVR processors are no exception), some interrupt is likely to get vectored to somewhere other than its proper service routine, and abnormal program operation will result; most likely, a crash.