Hex-encode non-ASCII random seeds in save files

The developer documentation claims that save files are long ASCII
strings.  This is mostly true, but there's nothing stopping a user
from entering non-ASCII characters as random seeds.  The ASCII
property of save files is useful, so encode seeds in hex before
writing them unless they consist only of printable ASCII characters.

Hex-encoded seeds are written under a new key, HEXSEED, to distinguish
them from unencoded seeds.  This means that old versions of the code
won't be able to load encoded seeds, but that's not a great loss:
seeds aren't generally portable between versions anyway.
This commit is contained in:
Ben Harris
2022-10-17 00:56:37 +01:00
parent 9f2eef8762
commit 304796f9f1

View File

@ -2061,8 +2061,27 @@ void midend_serialise(midend *me,
/*
* The current game description, the privdesc, and the random seed.
*/
if (me->seedstr)
wr("SEED", me->seedstr);
if (me->seedstr) {
/*
* Random seeds are not necessarily printable ASCII.
* Hex-encode the seed if necessary. Printable ASCII seeds
* are emitted unencoded for compatibility with older
* versions.
*/
int i;
for (i = 0; me->seedstr[i]; i++)
if (me->seedstr[i] < 32 || me->seedstr[i] >= 127)
break;
if (me->seedstr[i]) {
char *hexseed = bin2hex((unsigned char *)me->seedstr,
strlen(me->seedstr));
wr("HEXSEED", hexseed);
sfree(hexseed);
} else
wr("SEED", me->seedstr);
}
if (me->desc)
wr("DESC", me->desc);
if (me->privdesc)
@ -2264,6 +2283,15 @@ static const char *midend_deserialise_internal(
sfree(data.cparstr);
data.cparstr = val;
val = NULL;
} else if (!strcmp(key, "HEXSEED")) {
unsigned char *tmp;
int len = strlen(val) / 2; /* length in bytes */
tmp = hex2bin(val, len);
sfree(data.seed);
data.seed = snewn(len + 1, char);
memcpy(data.seed, tmp, len);
data.seed[len] = '\0';
sfree(tmp);
} else if (!strcmp(key, "SEED")) {
sfree(data.seed);
data.seed = val;