aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Harris <bjh21@bjh21.me.uk>2022-10-15 20:46:28 +0100
committerBen Harris <bjh21@bjh21.me.uk>2022-10-20 23:54:18 +0100
commite29d8a3ecad734967cdcf2d4ce222ab27e9c524b (patch)
treef452a6e7dafeab93f75c35e24ef58ae3ade09757
parentdbbe9d37500219b61132266029c1d8f42378c01c (diff)
downloadpuzzles-e29d8a3ecad734967cdcf2d4ce222ab27e9c524b.zip
puzzles-e29d8a3ecad734967cdcf2d4ce222ab27e9c524b.tar.gz
puzzles-e29d8a3ecad734967cdcf2d4ce222ab27e9c524b.tar.bz2
puzzles-e29d8a3ecad734967cdcf2d4ce222ab27e9c524b.tar.xz
Add an assertion to check the format of encoded parameters
Whenever the midend calls encode_params, it also checks that the result is a printable ASCII string that doesn't contain '#' or ':'. Parameter strings are embedded in save files, so they have to fit within ASCII. They can't contain '#' or ':' because those delimit the parameter section of a game ID. Nothing explicitly says they can't contain control characters, but those would be a particularly egregious violation of the recommendation that parameter strings be easy to type into a shell.
-rw-r--r--midend.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/midend.c b/midend.c
index 175b6f1..21ee560 100644
--- a/midend.c
+++ b/midend.c
@@ -383,6 +383,18 @@ game_params *midend_get_params(midend *me)
return me->ourgame->dup_params(me->params);
}
+static char *encode_params(midend *me, const game_params *params, bool full)
+{
+ char *encoded = me->ourgame->encode_params(params, full);
+
+ /* Assert that the params consist of printable ASCII containing
+ * neither '#' nor ':'. */
+ for (int i = 0; encoded[i]; i++)
+ assert(encoded[i] >= 32 && encoded[i] < 127 &&
+ encoded[i] != '#' && encoded[i] != ':');
+ return encoded;
+}
+
static void midend_set_timer(midend *me)
{
me->timing = (me->ourgame->is_timed &&
@@ -618,8 +630,8 @@ static const char *newgame_undo_deserialise_check(
* We check both params and cparams, to be as safe as possible.
*/
- old = me->ourgame->encode_params(me->params, true);
- new = me->ourgame->encode_params(data->params, true);
+ old = encode_params(me, me->params, true);
+ new = encode_params(me, data->params, true);
if (strcmp(old, new)) {
/* Set a flag to distinguish this deserialise failure
* from one due to faulty decoding */
@@ -627,8 +639,8 @@ static const char *newgame_undo_deserialise_check(
return "Undoing this new-game operation would change params";
}
- old = me->ourgame->encode_params(me->curparams, true);
- new = me->ourgame->encode_params(data->cparams, true);
+ old = encode_params(me, me->curparams, true);
+ new = encode_params(me, data->cparams, true);
if (strcmp(old, new)) {
ctx->refused = true;
return "Undoing this new-game operation would change params";
@@ -1390,7 +1402,7 @@ static void preset_menu_encode_params(midend *me, struct preset_menu *menu)
for (i = 0; i < menu->n_entries; i++) {
if (menu->entries[i].params) {
me->encoded_presets[menu->entries[i].id] =
- me->ourgame->encode_params(menu->entries[i].params, true);
+ encode_params(me, menu->entries[i].params, true);
} else {
preset_menu_encode_params(me, menu->entries[i].submenu);
}
@@ -1469,7 +1481,7 @@ struct preset_menu *midend_get_presets(midend *me, int *id_limit)
int midend_which_preset(midend *me)
{
- char *encoding = me->ourgame->encode_params(me->params, true);
+ char *encoding = encode_params(me, me->params, true);
int i, ret;
ret = -1;
@@ -1576,7 +1588,7 @@ config_item *midend_get_config(midend *me, int which, char **wintitle)
* the former is likely to persist across many code
* changes).
*/
- parstr = me->ourgame->encode_params(me->curparams, which == CFG_SEED);
+ parstr = encode_params(me, me->curparams, which == CFG_SEED);
assert(parstr);
if (which == CFG_DESC) {
rest = me->desc ? me->desc : "";
@@ -1720,7 +1732,7 @@ static const char *midend_game_id_int(midend *me, const char *id, int defmode)
newparams = me->ourgame->dup_params(me->params);
- tmpstr = me->ourgame->encode_params(newcurparams, false);
+ tmpstr = encode_params(me, newcurparams, false);
me->ourgame->decode_params(newparams, tmpstr);
sfree(tmpstr);
@@ -1792,7 +1804,7 @@ char *midend_get_game_id(midend *me)
{
char *parstr, *ret;
- parstr = me->ourgame->encode_params(me->curparams, false);
+ parstr = encode_params(me, me->curparams, false);
assert(parstr);
assert(me->desc);
ret = snewn(strlen(parstr) + strlen(me->desc) + 2, char);
@@ -1808,7 +1820,7 @@ char *midend_get_random_seed(midend *me)
if (!me->seedstr)
return NULL;
- parstr = me->ourgame->encode_params(me->curparams, true);
+ parstr = encode_params(me, me->curparams, true);
assert(parstr);
ret = snewn(strlen(parstr) + strlen(me->seedstr) + 2, char);
sprintf(ret, "%s#%s", parstr, me->seedstr);
@@ -2017,7 +2029,7 @@ void midend_serialise(midend *me,
* The current long-term parameters structure, in full.
*/
if (me->params) {
- char *s = me->ourgame->encode_params(me->params, true);
+ char *s = encode_params(me, me->params, true);
wr("PARAMS", s);
sfree(s);
}
@@ -2026,7 +2038,7 @@ void midend_serialise(midend *me,
* The current short-term parameters structure, in full.
*/
if (me->curparams) {
- char *s = me->ourgame->encode_params(me->curparams, true);
+ char *s = encode_params(me, me->curparams, true);
wr("CPARAMS", s);
sfree(s);
}