Ethereum responded by inventing gas, so that scripts would halt by failing once their gas is exhausted. This is horrific because it means the state machine is put into an indeterminate state.
If there is not enough gas, EVM is supposed to roll back to the pre-execution state.
It is the responsibility of the caller script to take precautionary measures.
Right. That's not why Ethereum is indeterminate - within one single block things are fine. The problem is across multiple blocks - if execution is dependant on block order, orphans and re-orgs can cause big problems.