Strict FEN parsing. Exit on setting invalid position via UCI.

fixes #6663, #6664, and a million others issues raised over the years.

This is similar to
https://github.com/official-stockfish/Stockfish/pull/4563/changes but
more conservative and errors are split between "Unsupported position"
and "Invalid FEN".

The FEN parser needs to be strict as a foundation for safety. It does
not specify much of the semantics, so this step is fairly simple. Parts
after the ep square are optional, however, since it's common, for
example in EPD notation.

Errors arising from positional semantics that were previously bucketed
under invalid FENs are now reported as "Unsupported position". Only
positions that are potentially problematic are designated as
unsupported. It is NOT guided by illegality of the position, but instead
by the ability of the engine to handle them correctly. This means that
some checks from the previous PR were removed.

std::exit is used instead of std::terminate so atexit handles will be
called.

Probably wise to run copilot on this or smth because I scribbled it
without much thought.

With these small changes and reduced, less controversial, scope I hope
this PR will finally make it and we will be done with these weekly
issues. I'll wait with putting it on fishtest until there's approval.

closes https://github.com/official-stockfish/Stockfish/pull/6665

No functional change
This commit is contained in:
Tomasz Sobczyk
2026-03-18 20:49:06 +01:00
committed by Disservin
parent 415f2ef11c
commit e38f5b2f53
7 changed files with 254 additions and 60 deletions
+11 -3
View File
@@ -25,6 +25,8 @@
#include <iosfwd>
#include <memory>
#include <new>
#include <optional>
#include <stdexcept>
#include <string>
#include "bitboard.h"
@@ -70,6 +72,12 @@ struct StateInfo {
// elements are not invalidated upon list resizing.
using StateListPtr = std::unique_ptr<std::deque<StateInfo>>;
// This error should be used whenever a position is suspected to be unsupported
// by the engine. In particular positions that may cause hard errors like segmentation fault.
struct PositionSetError: std::runtime_error {
using std::runtime_error::runtime_error;
};
// Position class stores information regarding the board representation as
// pieces, side to move, hash keys, castling info, etc. Important methods are
// do_move() and undo_move(), used by the search to update node info when
@@ -83,9 +91,9 @@ class Position {
Position& operator=(const Position&) = delete;
// FEN string input/output
Position& set(const std::string& fenStr, bool isChess960, StateInfo* si);
Position& set(const std::string& code, Color c, StateInfo* si);
std::string fen() const;
std::optional<PositionSetError> set(const std::string& fenStr, bool isChess960, StateInfo* si);
std::optional<PositionSetError> set(const std::string& code, Color c, StateInfo* si);
std::string fen() const;
// Position representation
Bitboard pieces() const; // All pieces