'Solidity bug hunting

I've got a piece of code below that attempts to implement a two-player game (with a wager on the line) of Tic-Tac-Toe, also known as Noughts and Crosses. It is said that this implementation contains at least 9 bugs which compromise the security of the game, but I only found one, which on line 61, I think selfdestruct() is not the way to send the pot. Can you guys find any more bugs and bring up some corresponding fixes? Any help is welcomed.

contract TicTacToe {
// game configuration
address [2] _playerAddress ; // address of both players
uint32 _turnLength ; // max time for each turn


// nonce material used to pick the first player
bytes32 _p1Commitment ;
uint8 _p2Nonce ;


// game state
uint8 [9] _board ; // serialized 3 x3 array
uint8 _currentPlayer ; // 0 or 1, indicating whose turn it is
uint256 _turnDeadline ; // deadline for submitting next move


// Create a new game , challenging a named opponent .
// The value passed in is the stake which the opponent must match .
// The challenger commits to its nonce used to determine first mover .
constructor ( address opponent , uint32 turnLength ,
bytes32 p1Commitment ) public {
_playerAddress [0] = msg . sender ;
_playerAddress [1] = opponent ;
_turnLength = turnLength ;
_p1Commitment = p1Commitment ;
}

// Join a game as the second player .
function joinGame ( uint8 p2Nonce ) public payable {
// only the specified opponent may join
if ( msg . sender != _playerAddress [1])
revert () ;
// must match player 1’s stake .
require ( msg . value >= this . balance ) ;
_p2Nonce = p2Nonce ;
}

// Revealing player 1’s nonce to choose who goes first .
function startGame ( uint8 p1Nonce ) public {
// must open the original commitment
require ( sha3 ( p1Nonce ) == _p1Commitment );
// XOR both nonces and take the last bit to pick the first player
_currentPlayer = ( p1Nonce ^ _p2Nonce ) & 0 x01 ;

// start the clock for the next move
_turnDeadline = block . number + _turnLength ;
}


// Submit a move
function playMove ( uint8 squareToPlay ) public {
// make sure correct player is submitting a move
require ( msg . sender != _playerAddress [ _currentPlayer ]) ;

// claim this square for the current player .
_board [ squareToPlay ] = _currentPlayer ;

// If the game is won , send the pot to the winner
if ( checkGameOver () )
selfdestruct ( msg . sender );

// Flip the current player
_currentPlayer ^= 0 x1 ;

// start the clock for the next move
_turnDeadline = block . number + _turnLength ;
}

// Default the game if a player takes too long to submit a move
function defaultGame () public {
if ( block . number > _turnDeadline )
selfdestruct ( msg . sender );
}
}


Solution 1:[1]

Okay, I will answer my own question.

  1. Line 42
  2. Line 54
  3. Line 54 again
  4. Line 61
  5. Line 72

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Emanuele Filiberto