How are transfer and send protecting against reentrancy
The EVM is withholding gas to starve attackers. That severely constrains what they can do before they
Since the 2300 gas will prevent callback even if EOA sends it with million gas?
Yes, it is bad form but the gas stimpend should protect this poorly-constructed function. The called contract will not have enough gas to change its state or very much at all.
However this will NOT stop it
That will pass all (99% ish) of the unspent gas to the called contract (attacker) and it could use the caller's inconsistent state to start bad things. The caller is vulnerable because the state is inconsistent. It has not, yet, updated data that should be updated.
send(), transfer() and call() hand over flow control to another contract, as do function calls, e.g. otherContract.doSomething(args). If the other contract is untrusted, meaning you did not write it yourself (many systems include multiple contracts for different concerns), then it is important to put the state in order first, then transfer flow control to the other contract.
The gas stipend (2300 gas) is a hack to protect some of the bad contracts some of the time. It is far better than you make good contracts all of the time.
- Check acceptable inputs - the transaction is allowed?
- Execute effects - update everything that should be updated.
- Safely interact with untrusted contracts - send, transfer, call, etc.
Hope it helps.