From e3cf1e3280f9a2729e0b7005a04648a5e8abbbf9 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 11 Apr 2011 21:37:23 +0200 Subject: [PATCH] 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. --- include/prototypes.h | 1 + src/lib/player/player.c | 30 ++++++++++++++++++++++++++++++ src/lib/subs/getstarg.c | 2 ++ src/lib/subs/onearg.c | 3 ++- src/lib/subs/snxtitem.c | 4 ++-- src/lib/subs/snxtsct.c | 5 +++-- 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/include/prototypes.h b/include/prototypes.h index 07a03b64..13c0ed7c 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -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); diff --git a/src/lib/player/player.c b/src/lib/player/player.c index 7f40b13e..d93211eb 100644 --- a/src/lib/player/player.c +++ b/src/lib/player/player.c @@ -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". diff --git a/src/lib/subs/getstarg.c b/src/lib/subs/getstarg.c index 20c6af61..731bed1e 100644 --- a/src/lib/subs/getstarg.c +++ b/src/lib/subs/getstarg.c @@ -34,6 +34,7 @@ #include #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; } diff --git a/src/lib/subs/onearg.c b/src/lib/subs/onearg.c index b97ce0a7..3784bdc7 100644 --- a/src/lib/subs/onearg.c +++ b/src/lib/subs/onearg.c @@ -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; diff --git a/src/lib/subs/snxtitem.c b/src/lib/subs/snxtitem.c index da8b86ad..bcb8f7d0 100644 --- a/src/lib/subs/snxtitem.c +++ b/src/lib/subs/snxtitem.c @@ -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)) { diff --git a/src/lib/subs/snxtsct.c b/src/lib/subs/snxtsct.c index 7657c456..01d8b597 100644 --- a/src/lib/subs/snxtsct.c +++ b/src/lib/subs/snxtsct.c @@ -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))