ref: 304796f9f184a783d0af21e445c690ed69de048b
parent: 9f2eef876275a451b015c22961130b2e507ddd49
author: Ben Harris <[email protected]>
date: Sun Oct 16 20:56:37 EDT 2022
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.
--- a/midend.c
+++ b/midend.c
@@ -2061,8 +2061,27 @@
/*
* 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 @@
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;