Commit Graph
1 Commits
Author SHA1 Message Date
Miloslav MacůrekandJoost VandeVondele 9700f6f206 Fix crash with UCI_LimitStrength and tablebases at the root
`Skill::pick_best()` assumes the root moves are sorted by score in descending order:

```cpp
Value topScore = rootMoves[0].score;
int   delta    = std::min(topScore - rootMoves[multiPV - 1].score, int(PawnValue));
```

That does not have to be so with Syzygy tablebases at the root, where the moves are ordered by `tbRank` instead. `rootMoves[0]` is then not the highest score and `delta` can go negative. Since `delta * (rng.rand<unsigned>() % int(weakness))` is evaluated as unsigned, a negative `delta` wraps to a large value and the `int(...)` cast overflows, so the `score + push >= maxScore` check never passes and `best` stays `Move::none()`. The caller

```cpp
std::swap(rootMoves[0],
          *std::find(rootMoves.begin(), rootMoves.end(),
                     skill.best ? skill.best : skill.pick_best(rootMoves, multiPV)));
```

then dereferences `end()`. The result is a crash, or sometimes `bestmove (none)` / an illegal move, in tablebase endgames when `UCI_LimitStrength` is set (or `Skill Level` is below 20).

The fix computes the score range over the candidate moves directly, so `delta` stays non-negative and a valid move is always returned.

**To reproduce**:
```
setoption name UCI_LimitStrength value true
setoption name UCI_Elo value 2900
setoption name SyzygyPath value <syzygy tablebases path>
position fen 8/8/8/4k3/8/8/3BKN2/8 b - - 0 1
go wtime 250 btime 250 winc 100 binc 100
```

You need to call the go command a couple of times before crash, after which is ends with

```
bestmove a1e5 ponder (none)
```

and on the next `go wtime 250 btime 250 winc 100 binc 100` it crashes printing:

```
info string Available processors: 0-31
info string Using 1 thread
info string NNUE evaluation using nn-af1339a6dea3.nnue (106MiB, (83248, 1024, 31, 32, 1))
info string Network replica 1: Shared memory.
```

Bench is unchanged, since this code only runs under `UCI_LimitStrength` / `Skill Level`.

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

No functional change
2026-07-10 20:17:23 +02:00