Make generation numbers catch more potential yields on input

getstarg(), snxtitem() and snxtsct() can yield the processor, because
they call getstring().  But only for null or empty arguments.  For
other arguments, we should call ef_make_stale(), to catch errors.
Problem: if a caller never passes null or empty arguments, it may rely
on these functions not yielding.  We'd get false positives.  In
general, we can't know whether that's the case.  But we do know in the
common special case of player arguments.  Call ef_make_stale() for
those.
This commit is contained in:
Markus Armbruster 2011-04-11 21:37:23 +02:00
parent 47b68a1c1f
commit e3cf1e3280
6 changed files with 40 additions and 5 deletions

View file

@ -363,6 +363,7 @@ extern int natpass(natid, char *);
extern struct player *player; /* current player's context */
extern char *praddr(struct player *);
extern void player_main(struct player *);
extern void make_stale_if_command_arg(char *);
/* more under Commands */
/* recvclient.c */
extern int recvclient(char *, int);

View file

@ -202,6 +202,36 @@ status(void)
return 1;
}
/* Is ARG one of the player's last command's arguments? */
static int
is_command_arg(char *arg)
{
int i;
for (i = 1; i < 128 && player->argp[i]; i++) {
if (arg == player->argp[i])
return 1;
}
return 0;
}
/*
* Make all objects stale if ARG is one of the player's command arguments.
* See ef_make_stale() for what "making stale" means.
* Useful for functions that prompt for missing arguments.
* These can yield the processor, so we'd like to call ef_make_stale()
* there. Except that leads to false positives when the caller passes
* an argument that is never null, and relies on the fact that the
* function doesn't yield then. We can't know that in general. But
* we do know in the common special case of command arguments.
*/
void
make_stale_if_command_arg(char *arg)
{
if (is_command_arg(arg))
ef_make_stale();
}
/*
* XXX This whole mess should be redone; execute block should
* start with "exec start", and should end with "exec end".

View file

@ -34,6 +34,7 @@
#include <string.h>
#include "misc.h"
#include "prototypes.h"
/*
* Get string argument.
@ -50,6 +51,7 @@ getstarg(char *input, char *prompt, char *buf)
return NULL;
} else {
strcpy(buf, input);
make_stale_if_command_arg(input);
}
return buf;
}

View file

@ -43,7 +43,8 @@ onearg(char *arg, char *prompt)
if (!arg || !*arg) {
if (!(arg = getstring(prompt, buf)))
return -1;
}
} else
make_stale_if_command_arg(arg);
n = atoi(arg);
if (n < 0)
return -1;

View file

@ -73,9 +73,9 @@ snxtitem(struct nstr_item *np, int type, char *str, char *prompt)
str = getstring(prompt, buf);
if (!str)
return 0;
}
} else
make_stale_if_command_arg(str);
if (*str == 0) {
/* empty string passed by player */
return 0;
}
if (type == EF_NATION && isalpha(*str)) {

View file

@ -44,7 +44,7 @@
/*
* setup the nstr_sect structure for sector selection.
* can select on either NS_ALL, NS_AREA, or NS_RANGE
* can select on either NS_ALL, NS_AREA, or NS_DIST
* iterate thru the "condarg" string looking
* for arguments to compile into the nstr.
* Using this function for anything but command arguments is usually
@ -63,7 +63,8 @@ snxtsct(struct nstr_sect *np, char *str)
if (!str || !*str) {
if (!(str = getstring("(sects)? ", buf)))
return 0;
}
} else
make_stale_if_command_arg(str);
switch (sarg_type(str)) {
case NS_AREA:
if (!sarg_area(str, &range))