mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
James Harvey points out that entering an invalid game ID can affect
the current midend state even if you don't subsequently enter a valid one. Reorganise midend_game_id_int() so that (just like midend_deserialise()) it does all its error checking before altering anything in the midend's persistent data, so that it either succeeds completely or fails before doing anything at all. [originally from svn r6045]
This commit is contained in:
70
midend.c
70
midend.c
@ -855,6 +855,8 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle)
|
|||||||
static char *midend_game_id_int(midend_data *me, char *id, int defmode)
|
static char *midend_game_id_int(midend_data *me, char *id, int defmode)
|
||||||
{
|
{
|
||||||
char *error, *par, *desc, *seed;
|
char *error, *par, *desc, *seed;
|
||||||
|
game_params *newcurparams, *newparams, *oldparams1, *oldparams2;
|
||||||
|
int free_params;
|
||||||
|
|
||||||
seed = strchr(id, '#');
|
seed = strchr(id, '#');
|
||||||
desc = strchr(id, ':');
|
desc = strchr(id, ':');
|
||||||
@ -894,18 +896,24 @@ static char *midend_game_id_int(midend_data *me, char *id, int defmode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must be reasonably careful here not to modify anything in
|
||||||
|
* `me' until we have finished validating things. This function
|
||||||
|
* must either return an error and do nothing to the midend, or
|
||||||
|
* return success and do everything; nothing in between is
|
||||||
|
* acceptable.
|
||||||
|
*/
|
||||||
|
newcurparams = newparams = oldparams1 = oldparams2 = NULL;
|
||||||
|
|
||||||
if (par) {
|
if (par) {
|
||||||
game_params *tmpparams;
|
newcurparams = me->ourgame->dup_params(me->params);
|
||||||
tmpparams = me->ourgame->dup_params(me->params);
|
me->ourgame->decode_params(newcurparams, par);
|
||||||
me->ourgame->decode_params(tmpparams, par);
|
error = me->ourgame->validate_params(newcurparams);
|
||||||
error = me->ourgame->validate_params(tmpparams);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
me->ourgame->free_params(tmpparams);
|
me->ourgame->free_params(newcurparams);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
if (me->curparams)
|
oldparams1 = me->curparams;
|
||||||
me->ourgame->free_params(me->curparams);
|
|
||||||
me->curparams = tmpparams;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now filter only the persistent parts of this state into
|
* Now filter only the persistent parts of this state into
|
||||||
@ -913,16 +921,50 @@ static char *midend_game_id_int(midend_data *me, char *id, int defmode)
|
|||||||
* received a params string in which case the whole lot is
|
* received a params string in which case the whole lot is
|
||||||
* persistent.
|
* persistent.
|
||||||
*/
|
*/
|
||||||
|
oldparams2 = me->params;
|
||||||
if (seed || desc) {
|
if (seed || desc) {
|
||||||
char *tmpstr = me->ourgame->encode_params(tmpparams, FALSE);
|
char *tmpstr;
|
||||||
me->ourgame->decode_params(me->params, tmpstr);
|
|
||||||
|
newparams = me->ourgame->dup_params(me->params);
|
||||||
|
|
||||||
|
tmpstr = me->ourgame->encode_params(newcurparams, FALSE);
|
||||||
|
me->ourgame->decode_params(newparams, tmpstr);
|
||||||
|
|
||||||
sfree(tmpstr);
|
sfree(tmpstr);
|
||||||
} else {
|
} else {
|
||||||
me->ourgame->free_params(me->params);
|
newparams = me->ourgame->dup_params(newcurparams);
|
||||||
me->params = me->ourgame->dup_params(tmpparams);
|
}
|
||||||
|
free_params = TRUE;
|
||||||
|
} else {
|
||||||
|
newcurparams = me->curparams;
|
||||||
|
newparams = me->params;
|
||||||
|
free_params = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
error = me->ourgame->validate_desc(newparams, desc);
|
||||||
|
if (error) {
|
||||||
|
if (free_params) {
|
||||||
|
if (newcurparams)
|
||||||
|
me->ourgame->free_params(newcurparams);
|
||||||
|
if (newparams)
|
||||||
|
me->ourgame->free_params(newparams);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we've got past all possible error points. Update the
|
||||||
|
* midend itself.
|
||||||
|
*/
|
||||||
|
me->params = newparams;
|
||||||
|
me->curparams = newcurparams;
|
||||||
|
if (oldparams1)
|
||||||
|
me->ourgame->free_params(oldparams1);
|
||||||
|
if (oldparams2)
|
||||||
|
me->ourgame->free_params(oldparams2);
|
||||||
|
|
||||||
sfree(me->desc);
|
sfree(me->desc);
|
||||||
sfree(me->privdesc);
|
sfree(me->privdesc);
|
||||||
me->desc = me->privdesc = NULL;
|
me->desc = me->privdesc = NULL;
|
||||||
@ -930,10 +972,6 @@ static char *midend_game_id_int(midend_data *me, char *id, int defmode)
|
|||||||
me->seedstr = NULL;
|
me->seedstr = NULL;
|
||||||
|
|
||||||
if (desc) {
|
if (desc) {
|
||||||
error = me->ourgame->validate_desc(me->params, desc);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
me->desc = dupstr(desc);
|
me->desc = dupstr(desc);
|
||||||
me->genmode = GOT_DESC;
|
me->genmode = GOT_DESC;
|
||||||
sfree(me->aux_info);
|
sfree(me->aux_info);
|
||||||
|
Reference in New Issue
Block a user