Why here is a Vulnerability

:1234: Code

contract Funny is Test {
    address public attacker;
    mapping(address => uint256) _balances;

    function setUp() public {
        attacker = makeAddr("attacker");
        _balances[attacker] = 100;
    }

    function _update(address from, address to, uint256 value) public {
        uint256 fromBalance = _balances[from];
        uint256 toBalance = _balances[to];

        unchecked {
            // Overflow not possible: value <= fromBalance <= totalSupply.
            _balances[from] = fromBalance - value;
            console.log("fromBalance:", _balances[attacker]);
            // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
            _balances[to] = toBalance + value;
            console.log("toBalance:", _balances[attacker]);
        }
    }

    function testUpdate() public {
        _update(attacker, attacker, 100);
        assertEq(_balances[attacker], 200);
    }
}

Question

Why the attacker balance increase to 200. i use console.log , the balance has been changed to 0 after
_balances[from] = fromBalance - value;, but why it suddenly be 200?

To put it simply, in this case:

fromBalance = toBalance = _balances[attacker] = 100;

This vulnerability is known as self transfer.

Thx bro! That's clear. You mean the uint256 toBalance have been defined as 100 at the beginning. So _balances[to] = toBalance + value; equals _balances[to] = 100 + 100;, right?

Correct : ) You can use console.log to make sure.