Skip to content

reject en-passant tokens the parser cannot map - #95

Merged
garak merged 1 commit into
p-chess:masterfrom
timndus:fix/fen-ep-token-character-class
Oct 21, 2026
Merged

garak merged 1 commit into
p-chess:masterfrom
timndus:fix/fen-ep-token-character-class

Conversation

@timndus

@timndus timndus commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

What

validateFen()'s ep criterion is /^(-|[a-h][3|6])$/. Inside a character class | is a literal, so the criterion is "-, or a file + 3/|/6" — a|, e|, h|, … all pass with code 0 ("No errors").

Chess::load() then reads Board::SQUARES[$tokens[3]]. a| is an undefined key: PHP 8 raises an E_WARNING ("Undefined array key"), $epSquare stays null, and fen() prints -:

validateFen("… b KQkq a| 0 1")  → 0
WARNING: Undefined array key "a|" (Chess.php:122)
epSquare = NULL, fen() = "… b KQkq - 0 1"

So the validator accepts a string the parser cannot represent. Whether that surfaces as an error depends entirely on the caller: with Laravel's HandleExceptions (or any handler that throws on warnings) the warning throws; with error_reporting(0), @, or a plain script the same FEN loads and is keyed/echoed verbatim. In chessable-b1 that produced a 422 that rested on the framework error handler rather than on the FEN itself, plus a cache key no valid spelling can produce.

Change

[36] is the intended set; no valid ep square contains |. This only moves <file>| tokens from accepted to error code 4 — every currently valid FEN keeps its verdict.

Test

New FenTest row, ['8/8/8/8/8/8/8/8 b - a| 0 1', 4]. It fails on master (Failed asserting that 0 matches expected 4) and passes with the fix.

Full suite: 282 tests, 1 skipped (existing slow perft). php-cs-fixer and PHPStan level 8 clean.

`[3|6]` is a character class of `3`, `|` and `6`, so every `<file>|`
spelling (`a|`, `e|`, ...) passes `validateFen()` with "No errors".
`Chess::load()` then maps the token through `Board::SQUARES[$token]`,
misses, and only emits an `E_WARNING` ("Undefined array key"), leaving
`epSquare` null and `fen()` printing `-`.

Reject the pipe at the gate instead: `[36]` is the intended set, and no
valid en-passant square contains `|`.

Covered by a new FenTest data row, which fails on master
(`Failed asserting that 0 matches expected 4`).
@garak
garak merged commit bf768dc into p-chess:master Oct 21, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants