shithub: puzzles

Download patch

ref: 02e5e93046d1ee2ce7acde629a6562db9b36fa5d
parent: 879a6922b0c59108de91f191926d0dde62cd2bd6
author: Ben Harris <[email protected]>
date: Sun Oct 16 14:31:54 EDT 2022

Add more validation to midend deserialisation routine

These are all pretty obvious and enforce constraints that would
otherwise be enforced by segfault.

--- a/midend.c
+++ b/midend.c
@@ -2265,15 +2265,15 @@
             } else if (!strcmp(key, "TIME")) {
                 data.elapsed = (float)atof(val);
             } else if (!strcmp(key, "NSTATES")) {
+                if (data.states) {
+                    ret = "Two state counts provided in save file";
+                    goto cleanup;
+                }
                 data.nstates = atoi(val);
                 if (data.nstates <= 0) {
                     ret = "Number of states in save file was negative";
                     goto cleanup;
                 }
-                if (data.states) {
-                    ret = "Two state counts provided in save file";
-                    goto cleanup;
-                }
                 data.states = snewn(data.nstates, struct midend_state_entry);
                 for (i = 0; i < data.nstates; i++) {
                     data.states[i].state = NULL;
@@ -2282,21 +2282,22 @@
                 }
             } else if (!strcmp(key, "STATEPOS")) {
                 data.statepos = atoi(val);
-            } else if (!strcmp(key, "MOVE")) {
+            } else if (!strcmp(key, "MOVE") ||
+                       !strcmp(key, "SOLVE") ||
+                       !strcmp(key, "RESTART")) {
+                if (!data.states) {
+                    ret = "No state count provided in save file";
+                    goto cleanup;
+                }
                 gotstates++;
-                data.states[gotstates].movetype = MOVE;
+                if (!strcmp(key, "MOVE"))
+                    data.states[gotstates].movetype = MOVE;
+                else if (!strcmp(key, "SOLVE"))
+                    data.states[gotstates].movetype = SOLVE;
+                else
+                    data.states[gotstates].movetype = RESTART;
                 data.states[gotstates].movestr = val;
                 val = NULL;
-            } else if (!strcmp(key, "SOLVE")) {
-                gotstates++;
-                data.states[gotstates].movetype = SOLVE;
-                data.states[gotstates].movestr = val;
-                val = NULL;
-            } else if (!strcmp(key, "RESTART")) {
-                gotstates++;
-                data.states[gotstates].movetype = RESTART;
-                data.states[gotstates].movestr = val;
-                val = NULL;
             }
         }
 
@@ -2305,6 +2306,10 @@
     }
 
     data.params = me->ourgame->default_params();
+    if (!data.parstr) {
+        ret = "Long-term parameters in save file are missing";
+        goto cleanup;
+    }
     me->ourgame->decode_params(data.params, data.parstr);
     if (me->ourgame->validate_params(data.params, true)) {
         ret = "Long-term parameters in save file are invalid";
@@ -2311,6 +2316,10 @@
         goto cleanup;
     }
     data.cparams = me->ourgame->default_params();
+    if (!data.cparstr) {
+        ret = "Short-term parameters in save file are missing";
+        goto cleanup;
+    }
     me->ourgame->decode_params(data.cparams, data.cparstr);
     if (me->ourgame->validate_params(data.cparams, false)) {
         ret = "Short-term parameters in save file are invalid";
@@ -2340,6 +2349,10 @@
         ret = "Game position in save file is out of range";
     }
 
+    if (!data.states) {
+        ret = "No state count provided in save file";
+        goto cleanup;
+    }
     data.states[0].state = me->ourgame->new_game(
         me, data.cparams, data.privdesc ? data.privdesc : data.desc);