shithub: puzzles

Download patch

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;