From: PatR Date: Fri, 5 Aug 2016 00:42:26 +0000 (-0700) Subject: option parsing crash: 'playmode' without value X-Git-Tag: NetHack-3.6.1_RC01~629 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=694b32cae267134598465ce3d3483483a9dac848;p=nethack option parsing crash: 'playmode' without value Reported directly to devteam, specifying the playmode option without appending a value caused a segfault during options parsing. The argument passed to string_for_opt() ought to have been False for "not optional" to trigger a "bad syntax" message, but even then the playmode parsing needs to check for Null to prevent the crash. "Bad syntax" is awfully vague. In cases like this, we can be more precise. Now it will say "Missing value" instead. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index cbf74c283..d6031ea65 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -328,6 +328,7 @@ eating the corpse of a unique non-named monster (Wizard of Yendor, Oracle, Chromatic Dragon, others) gave "The the tastes ..." when escaping the dungeon, change "you were here" annotation in dungeon overview to "you left from here" +option parsing will crash if 'playmode' option is present without a value Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/options.c b/src/options.c index 1245c276b..4edc94fe0 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1461102048 2016/04/19 21:40:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.268 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1470357737 2016/08/05 00:42:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.279 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -500,6 +500,7 @@ static boolean initial, from_file; STATIC_DCL void FDECL(nmcpy, (char *, const char *, int)); STATIC_DCL void FDECL(escapes, (const char *, char *)); STATIC_DCL void FDECL(rejectoption, (const char *)); +STATIC_DCL void FDECL(badoptmsg, (const char *, const char *)); STATIC_DCL void FDECL(badoption, (const char *)); STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P)); STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P)); @@ -927,40 +928,43 @@ const char *optname; } STATIC_OVL void -badoption(opts) +badoptmsg(opts, reason) const char *opts; +const char *reason; /* "Bad syntax" or "Missing value" */ { + const char *linesplit = ""; + if (!initial) { if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1)) option_help(); else - pline("Bad syntax: %s. Enter \"?g\" for help.", opts); + pline("%s: %s. Enter \"?g\" for help.", reason, opts); return; - } #ifdef MAC - else + } else { return; #endif + } - if (from_file) - raw_printf("Bad syntax in OPTIONS in %s: %s%s.\n", configfile, #ifdef WIN32 - "\n", -#else - "", + linesplit = "\n"; #endif - opts); + if (from_file) + raw_printf("%s in OPTIONS in %s: %s%s.\n", + reason, configfile, linesplit, opts); else - raw_printf("Bad syntax in NETHACKOPTIONS: %s%s.\n", -#ifdef WIN32 - "\n", -#else - "", -#endif - opts); + raw_printf("%s in NETHACKOPTIONS: %s%s.\n", + reason, linesplit, opts); wait_synch(); } +STATIC_OVL void +badoption(opts) +const char *opts; +{ + badoptmsg(opts, "Bad syntax"); +} + STATIC_OVL char * string_for_opt(opts, val_optional) char *opts; @@ -975,7 +979,7 @@ boolean val_optional; if (!colon || !*++colon) { if (!val_optional) - badoption(opts); + badoptmsg(opts, "Missing value"); return (char *) 0; } return colon; @@ -2700,7 +2704,9 @@ boolean tinitial, tfrom_file; bad_negation(fullname, FALSE); if (duplicate || negated) return; - op = string_for_opt(opts, TRUE); + op = string_for_opt(opts, FALSE); + if (!op) + return; if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) { wizard = discover = FALSE; } else if (!strncmpi(op, "explore", 6)