Win by Segfault and Other Notes on Exploiting Chess Engines
chess.resistant.tech
chess.resistant.tech
position fen 4kb1r/B2pqBpp/3P1n2/Q7/PP2PPP1/1K4RP/8/8 w - - 0 1
go searchmoves
With a debug build, Stockfish crashes immediately on the following line (Position::do_move, position.cpp:726): assert(type_of(captured) != KING);
As noted in the article, the position is invalid as the black king is checked on white's turn. During move evaluation, the king capture is considered as a possible move for white, which crashes in the assertion.In a release build, without that assumption, Stockfish happily continues examining this line without a black king present on the board, and somewhere deep in the evaluation attempts to locate the black king (evaluate.cpp:540):
const Square ksq = pos.square<KING>(Us);
This fails, producing a ksq value which is undefined: it uses tzcnt, which returns an "undefined" value if the register is zero (and it is, because there is no king so the bitboard is zero). The likely value is 0x40, which is out of bounds; any later operation that tries to index by this will explode in exciting ways. For example, in the same evaluation function, we have b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
which indexes an array called BishopMagics with ksq; this goes out of bounds and accesses a wild pointer.I was unable to reproduce the second crash, "Win by Segfault Attack".
Also, this would be more interesting on previous versions of SF before the NN eval, as the handcrafted eval has been battle hardened for years.
That said, this is still a cool analysis to identify a concrete exploit!
Illegal position, sure, but validating it first would not affect the fast core logic.
The lack of validation is surprising because the code looks extremely clean and well structured otherwise.
The promotion of an opponents piece could end in a game where you promote your pawn to their knight which becomes a checkmate as the pieces were organized in a way that blocked the king.
So you could promote to king, but that would be a liability so it made no sense.
A better exploit would be to promote to your opponent’s king in a way that immediately puts it in checkmate.
Law XIII said, "When a pawn has reached the eighth square, the player has the option of selecting a piece, whether such piece has previously been lost or not, whose names and powers it shall then assume, or of deciding that it shall remain a pawn."
No restriction on piece type or color. So under those laws, promoting to a king or a piece of the other color would have been legal.
From what I've read though, this sounds like it was sloppy wording, and the normal promotion rules we are familiar with today were actually intended, except for the option of remaining a pawn, which was obviously intentional since it is explicitly called out, and was actually the controversial part of that rule.
Who gets to move that piece? It would be your opponent wouldn't it?
More an amusing curiosity than anything truly interesting. It would rarely be practical to give your opponent another piece. Puzzle creators have apparently come up with a few ways to make a scenario where that would be a move required to win, but my understanding is that none of them are terribly realistic.
Before that you could promote a pawn to a rook and then castle vertically across the board.