Looping forever is the same as if you ran the recursive version on a hypothetical machine with unlimited stack memory, so it didn't really change semantics.
But we aren't running on a hypothetical machine. That's the whole argument with the "define everything" crowd. Those two programs are different on my machine. Is that my fault or the compiler's fault?
People say "I just want my machine to do what my machine does when I dereference a pointer at address 0, why is my compiler making my program do something different?" Why can't I say the same thing in my case?
No, the argument against undefined behavior is that it makes errors silent. I don't care whether dereferencing a null pointer causes a segfault, an exception or something else, but it shouldn't cause the program to run as if nothing is wrong.
In a multithreaded program, one of the implementations I described crashes my program and one makes everything else but the stuck thread run just fine.