Bug#1148568: bsdgames: sail is unplayable where plain char is unsigned: two more games (adventure, trek)
adam margulies
aam at fastmail.fm
Mon Sep 21 01:32:50 BST 2026
Control: retitle -1 bsdgames: sail, adventure and trek misbehave where plain char is unsigned (arm64, armhf, ppc64el, s390x, riscv64)
Dear Maintainer,
after reporting sail I went through the rest of the package for the same
assumption. Two more games are affected; a second patch is attached
(0024-..., DEP-3, applies with -p1 on top of the sail patch or without it).
adventure (bsdgames-adventure): end of input is never noticed.
$ printf 'no\n' | /usr/games/bsdgames-adventure | head -c 100000 | grep -c 'Give me a break'
2479
getin() in adventure/io.c stores getchar() in a char and then has "case EOF:"
in a switch on that char. With unsigned char the case is unreachable, so on
^D, or when piped input runs out, the game prints "Give me a break!!" and
"I don't know that word." for ever (at full speed) instead of "user closed
input stream, quitting...". The same source built with -fsigned-char prints
that message and exits 0.
trek: a lost game gets the bonus for winning.
Start trek, take a short novice game, and "destruct". On arm64 the score is
Penalty for 5 klingons remaining -2000
Bonus for winning a novice game 100
Penalty for getting killed -500
Move.endgame (trek/trek.h) is a plain char; lose() sets it to -1, win() to 1,
and score() tests "Move.endgame > 0". 255 > 0. Built with -fsigned-char the
bonus line is absent and the total is 100 lower.
How I looked, so that you can judge what may have been missed:
* every game built with gcc 14 and -funsigned-char -Wtype-limits
-Wswitch-outside-range: the only relevant diagnostics in the whole tree
are sail/sync.c:260 and adventure/io.c:88 (both "case EOF" on a char);
no comparison of a plain char with a negative constant or with EOF exists
anywhere else;
* every source file through -fsyntax-only -funsigned-char -Wsign-conversion,
looking for negative constants converted to char: 93 in sail/globals.c
(the tables of the first patch) and one in trek/lose.c (endgame = -1);
* hack keeps its small signed numbers in "schar", which config.h already
defines as short int for exactly this reason;
* the 230-odd remaining scalar plain-char variables and the char arrays
that are assigned differences at run time were read through: letters,
symbols, flags and counts that never go negative;
* adventure and trek were then built twice, with -fsigned-char and with
-funsigned-char, and behave differently exactly as described; with the
patch the unsigned build behaves like the signed one.
Not related to signedness, but seen on the way: several games loop at end of
input whatever the architecture (monop asks "How many players?" for ever,
atc, backgammon, teachgammon and snake likewise fill the terminal).
More information about the Pkg-games-devel
mailing list