diff --git a/dat/GENFILES b/dat/GENFILES new file mode 100755 index 000000000..5ffd00107 --- /dev/null +++ b/dat/GENFILES @@ -0,0 +1,47 @@ +#!/usr/bin/perl + +# 2 sections: +# *.lev entries are generated by reading *.des +# hardcoded entries are in __DATA__ + +($dir = $0) =~ s!^(.*/)(.*)!$1!; + +print "T (files generated by lev_comp at playground creation time)\n"; + +foreach $des (<$dir*.des>){ + open IN, "<", $des or warn("Can't open $des: $!"); + while(){ + m/^(MAZE|LEVEL):\s*"(.*?)"/ && do { + print "F $2.lev\n"; + }; + } + close IN; +} +while(){ + print; +} + +__DATA__ +T (tile files optionally generated for X ports at playground creation time) +F pet_mark.xbm +F rip.xpm +F x11tiles +T (files generated for Qt interface on Mac OS X) +F nethack.icns +F Info.plist +T (files generated for win32 at compile time) +F porthelp +F dlb.lst +T (files generated for win32 tty at compile time) +F ttyoptions +T (files generated for win32 gui at compile time) +F guioptions +T (files generated by makedefs at playground creation time) +F data +F dungeon.pdf +F options +F oracles +F quest.dat +F rumors +T (file generated by dgn_comp at playground creation time) +F dungeon diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 323d911df..96361d68a 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -185,6 +185,13 @@ with menustyle:Full, picking 'A - autoselect all' when putting items into a container actually took everything out of that container add missing 'A - autoselect all' choice for menustyle:Full when taking items out while looting a container +fix odd wording "The boulder triggers and fills a pit" +^X status feedback: don't report "not wearing any armor" when wearing a shield +attempting to #ride a long worm's tail could trigger impossible "worm_cross + checking for non-adjacent location?" +avoid "The " in "The falls down stairs." +avoid potential buffer overflow if object with very long name knocks other + objects down stairs when dropped, thrown, or kicked there Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 74e6ef0a6..6468cb4d3 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1541145514 2018/11/02 07:58:34 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.645 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1541719965 2018/11/08 23:32:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.647 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -172,6 +172,7 @@ E boolean NDECL(status_hilite_menu); /* ### cmd.c ### */ +E char NDECL(randomkey); E int NDECL(doconduct); E int NDECL(domonability); E char FDECL(cmd_from_func, (int NDECL((*)))); @@ -784,7 +785,7 @@ E void FDECL(unlock_file, (const char *)); E boolean FDECL(can_read_file, (const char *)); #endif E void FDECL(config_error_init, (BOOLEAN_P, const char *, BOOLEAN_P)); -E void FDECL(config_error_add, (const char *, ...)) PRINTF_F(1, 2); +E void FDECL(config_erradd, (const char *)); E int NDECL(config_error_done); E boolean FDECL(read_config_file, (const char *, int)); E void FDECL(check_recordfile, (const char *)); @@ -1879,6 +1880,7 @@ E void VDECL(There, (const char *, ...)) PRINTF_F(1, 2); E void VDECL(verbalize, (const char *, ...)) PRINTF_F(1, 2); E void VDECL(raw_printf, (const char *, ...)) PRINTF_F(1, 2); E void VDECL(impossible, (const char *, ...)) PRINTF_F(1, 2); +E void VDECL(config_error_add, (const char *, ...)) PRINTF_F(1, 2); /* ### polyself.c ### */ diff --git a/include/flag.h b/include/flag.h index 58cda7838..b8c6a5993 100644 --- a/include/flag.h +++ b/include/flag.h @@ -237,6 +237,7 @@ struct instance_flags { * behaviour of various NetHack functions and probably warrant * a structure of their own elsewhere some day. */ + boolean debug_fuzzer; /* fuzz testing */ boolean defer_plname; /* X11 hack: askname() might not set plname */ boolean herecmd_menu; /* use menu when mouseclick on yourself */ boolean invis_goldsym; /* gold symbol is ' '? */ diff --git a/src/allmain.c b/src/allmain.c index be99150be..99a53e77f 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -397,7 +397,7 @@ boolean resuming; continue; } - if (iflags.sanity_check) + if (iflags.sanity_check || iflags.debug_fuzzer) sanity_check(); #ifdef CLIPPING diff --git a/src/cmd.c b/src/cmd.c index 9b4579857..c783a5b2e 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1541235664 2018/11/03 09:01:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.298 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1541631031 2018/11/07 22:50:31 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.299 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -298,6 +298,8 @@ pgetchar() /* courtesy of aeb@cwi.nl */ { register int ch; + if (iflags.debug_fuzzer) + return randomkey(); if (!(ch = popch())) ch = nhgetch(); return (char) ch; @@ -942,6 +944,11 @@ wiz_level_change(VOID_ARGS) STATIC_PTR int wiz_panic(VOID_ARGS) { + if (iflags.debug_fuzzer) { + u.uhp = u.uhpmax = 1000; + u.uen = u.uenmax = 1000; + return 0; + } if (yn("Do you want to call panic() and end your game?") == 'y') panic("Crash test."); return 0; @@ -2426,7 +2433,7 @@ int final; you_are(buf, ""); } /* report 'nudity' */ - if (!uarm && !uarmu && !uarmc && !uarmg && !uarmf && !uarmh) { + if (!uarm && !uarmu && !uarmc && !uarms && !uarmg && !uarmf && !uarmh) { if (u.uroleplay.nudist) enl_msg(You_, "do", "did", " not wear any armor", ""); else @@ -4354,6 +4361,29 @@ int NDECL((*cmd_func)); return FALSE; } +char +randomkey() +{ + static int i = 0; + char c; + + switch (rn2(12)) { + default: c = '\033'; break; + case 0: c = '\n'; break; + case 1: + case 2: + case 3: + case 4: c = (char)(' ' + rn2((int)('~' - ' '))); break; + case 5: c = '\t'; break; + case 6: c = (char)('a' + rn2((int)('z' - 'a'))); break; + case 7: c = (char)('A' + rn2((int)('Z' - 'A'))); break; + case 8: c = extcmdlist[(i++) % SIZE(extcmdlist)].key; break; + case 9: c = '#'; break; + } + + return c; +} + int ch2spkeys(c, start, end) char c; @@ -5563,6 +5593,8 @@ readchar() register int sym; int x = u.ux, y = u.uy, mod = 0; + if (iflags.debug_fuzzer) + return randomkey(); if (*readchar_queue) sym = *readchar_queue++; else diff --git a/src/do.c b/src/do.c index 614b4cd17..953dd85ff 100644 --- a/src/do.c +++ b/src/do.c @@ -178,7 +178,9 @@ const char *verb; if (Blind && (x == u.ux) && (y == u.uy)) { You_hear("a CRASH! beneath you."); } else if (!Blind && cansee(x, y)) { - pline_The("boulder %s%s.", t->tseen ? "" : "triggers and ", + pline_The("boulder %s%s.", + (t->ttyp == TRAPDOOR && !t->tseen) + ? "triggers and " : "", t->ttyp == TRAPDOOR ? "plugs a trap door" : t->ttyp == HOLE ? "plugs a hole" @@ -1059,6 +1061,8 @@ doup() return 1; } if (ledger_no(&u.uz) == 1) { + if (iflags.debug_fuzzer) + return 0; if (yn("Beware, there will be no return! Still climb?") != 'y') return 0; } diff --git a/src/dokick.c b/src/dokick.c index 1bea20ab6..85d461696 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dokick.c $NHDT-Date: 1517128663 2018/01/28 08:37:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.113 $ */ +/* NetHack 3.6 dokick.c $NHDT-Date: 1541842623 2018/11/10 09:37:03 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.122 $ */ /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1722,22 +1722,27 @@ register struct obj *otmp; register boolean nodrop; long num; { - char obuf[BUFSZ]; + char *optr = 0, obuf[BUFSZ], xbuf[BUFSZ]; - Sprintf(obuf, "%s%s", - (otmp->otyp == CORPSE && type_is_pname(&mons[otmp->corpsenm])) - ? "" - : "The ", - cxname(otmp)); + if (otmp->otyp == CORPSE) { + /* Tobjnam() calls xname() and would yield "The corpse"; + we want more specific "The newt corpse" or "Medusa's corpse" */ + optr = upstart(corpse_xname(otmp, (char *) 0, CXN_PFX_THE)); + } else { + optr = Tobjnam(otmp, (char *) 0); + } + Strcpy(obuf, optr); if (num) { /* means: other objects are impacted */ - Sprintf(eos(obuf), " %s %s object%s", otense(otmp, "hit"), - num == 1L ? "another" : "other", num > 1L ? "s" : ""); + /* 3.6.2: use a separate buffer for the suffix to avoid risk of + overrunning obuf[] (let pline() handle truncation if necessary) */ + Sprintf(xbuf, " %s %s object%s", otense(otmp, "hit"), + (num == 1L) ? "another" : "other", (num > 1L) ? "s" : ""); if (nodrop) - Sprintf(eos(obuf), "."); + Sprintf(eos(xbuf), "."); else - Sprintf(eos(obuf), " and %s %s.", otense(otmp, "fall"), gate_str); - pline1(obuf); + Sprintf(eos(xbuf), " and %s %s.", otense(otmp, "fall"), gate_str); + pline("%s%s", obuf, xbuf); } else if (!nodrop) pline("%s %s %s.", obuf, otense(otmp, "fall"), gate_str); } diff --git a/src/end.c b/src/end.c index c423fbcde..9cd4d40a0 100644 --- a/src/end.c +++ b/src/end.c @@ -330,6 +330,8 @@ int sig_unused UNUSED; int done2() { + if (iflags.debug_fuzzer) + return 0; if (!paranoid_query(ParanoidQuit, "Really quit?")) { #ifndef NO_SIGNAL (void) signal(SIGINT, (SIG_RET_TYPE) done1); @@ -602,7 +604,7 @@ VA_DECL(const char *, str) /* XXX can we move this above the prints? Then we'd be able to * suppress "it may be possible to rebuild" based on dosave0() * or say it's NOT possible to rebuild. */ - if (program_state.something_worth_saving) { + if (program_state.something_worth_saving && !iflags.debug_fuzzer) { set_error_savefile(); if (dosave0()) { /* os/win port specific recover instructions */ @@ -1043,6 +1045,14 @@ int how; bot(); } + if (iflags.debug_fuzzer) { + if (!(program_state.panicking || how == PANICKED)) { + savelife(how); + killer.name[0] = 0; + killer.format = 0; + return; + } + } else if (how == ASCENDED || (!killer.name[0] && how == GENOCIDED)) killer.format = NO_KILLER_PREFIX; /* Avoid killed by "a" burning or "a" starvation */ diff --git a/src/files.c b/src/files.c index 77ff211c8..2b2a67f56 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 files.c $NHDT-Date: 1526382938 2018/05/15 11:15:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.240 $ */ +/* NetHack 3.6 files.c $NHDT-Date: 1541719971 2018/11/08 23:32:51 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.242 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2494,7 +2494,7 @@ char *origbuf; n = atoi(bufp); if (n < 1) { config_error_add( - "Illegal value in MAX_STATUENAME_RANK (minimum is 1)."); + "Illegal value in MAX_STATUENAME_RANK (minimum is 1)."); return FALSE; } sysopt.tt_oname_maxrank = n; @@ -2736,7 +2736,7 @@ struct _config_error_frame { struct _config_error_frame *next; }; -struct _config_error_frame *config_error_data = (struct _config_error_frame *)0; +static struct _config_error_frame *config_error_data = 0; void config_error_init(from_file, sourcename, secure) @@ -2745,7 +2745,7 @@ const char *sourcename; boolean secure; { struct _config_error_frame *tmp = (struct _config_error_frame *) - alloc(sizeof(struct _config_error_frame)); + alloc(sizeof (struct _config_error_frame)); tmp->line_num = 0; tmp->num_errors = 0; @@ -2754,8 +2754,8 @@ boolean secure; tmp->secure = secure; tmp->origline[0] = '\0'; if (sourcename && sourcename[0]) { - (void) strncpy(tmp->source, sourcename, sizeof(tmp->source)-1); - tmp->source[sizeof(tmp->source)-1] = '\0'; + (void) strncpy(tmp->source, sourcename, sizeof (tmp->source) - 1); + tmp->source[sizeof (tmp->source) - 1] = '\0'; } else tmp->source[0] = '\0'; @@ -2778,49 +2778,43 @@ const char *line; ced->line_num++; ced->origline_shown = FALSE; if (line && line[0]) { - (void) strncpy(ced->origline, line, sizeof(ced->origline)-1); - ced->origline[sizeof(ced->origline)-1] = '\0'; + (void) strncpy(ced->origline, line, sizeof (ced->origline) - 1); + ced->origline[sizeof (ced->origline) - 1] = '\0'; } else ced->origline[0] = '\0'; return TRUE; } -/*VARARGS1*/ -void config_error_add -VA_DECL(const char *, str) +/* varargs 'config_error_add()' moved to pline.c */ +void +config_erradd(buf) +const char *buf; { - char buf[BUFSZ]; char lineno[QBUFSZ]; - VA_START(str); - VA_INIT(str, char *); - - Vsprintf(buf, str, VA_ARGS); + if (!buf || !*buf) + buf = "Unknown error"; if (!config_error_data) { - pline("%s.", *buf ? buf : "Unknown error"); + /* assumes pline() is using raw_printf() as this stage */ + pline("config_error_add: %s.", buf); wait_synch(); return; } config_error_data->num_errors++; - if (!config_error_data->origline_shown - && !config_error_data->secure) { + if (!config_error_data->origline_shown && !config_error_data->secure) { pline("\n%s", config_error_data->origline); config_error_data->origline_shown = TRUE; } - if (config_error_data->line_num > 0 - && !config_error_data->secure) { - Sprintf(lineno, "Line %i: ", config_error_data->line_num); + if (config_error_data->line_num > 0 && !config_error_data->secure) { + Sprintf(lineno, "Line %d: ", config_error_data->line_num); } else lineno[0] = '\0'; - pline("%s %s%s.", - config_error_data->secure ? "Error:" : " *", - lineno, - *buf ? buf : "Unknown error"); - VA_END(); + pline("%s %s%s.", config_error_data->secure ? "Error:" : " *", + lineno, buf); } int @@ -2833,17 +2827,14 @@ config_error_done() return 0; n = config_error_data->num_errors; if (n) { - pline("\n%i error%s in %s.\n", n, + pline("\n%d error%s in %s.\n", n, (n > 1) ? "s" : "", *config_error_data->source ? config_error_data->source : configfile); wait_synch(); } - config_error_data = tmp->next; - free(tmp); - return n; } @@ -3108,7 +3099,8 @@ boolean FDECL((*proc), (char *)); char *section; char *bufp = find_optparam(buf); if (!bufp) { - config_error_add("Format is CHOOSE=section1,section2,..."); + config_error_add( + "Format is CHOOSE=section1,section2,..."); rv = FALSE; free(buf); buf = (char *) 0; @@ -3199,8 +3191,8 @@ int which_set; } if (!chosen_symset_end) config_error_add("Missing finish for symset \"%s\"", - symset[which_set].name ? symset[which_set].name - : "unknown"); + symset[which_set].name ? symset[which_set].name + : "unknown"); config_error_done(); diff --git a/src/hack.c b/src/hack.c index 0593bd683..7a5e48116 100644 --- a/src/hack.c +++ b/src/hack.c @@ -2534,6 +2534,11 @@ pickup_checks() You("could drink the %s...", hliquid("water")); else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN)) pline("It won't come off the hinges."); + else if (IS_ALTAR(lev->typ)) + pline("Moving the altar would be a very bad idea."); + else if (lev->typ == STAIRS) + pline_The("stairs are solidly fixed to the %s.", + surface(u.ux, u.uy)); else There("is nothing here to pick up."); return 0; diff --git a/src/mail.c b/src/mail.c index 067dab09f..3f47e3a55 100644 --- a/src/mail.c +++ b/src/mail.c @@ -642,6 +642,8 @@ struct obj *otmp UNUSED; return; #endif /* SIMPLE_MAIL */ #ifdef DEF_MAILREADER /* This implies that UNIX is defined */ + if (iflags.debug_fuzzer) + return; display_nhwindow(WIN_MESSAGE, FALSE); if (!(mr = nh_getenv("MAILREADER"))) mr = DEF_MAILREADER; @@ -674,6 +676,8 @@ ckmailstatus() { struct mail_info *brdcst; + if (iflags.debug_fuzzer) + return; if (u.uswallow || !flags.biff) return; diff --git a/src/mkobj.c b/src/mkobj.c index 558be1dc6..8442f680c 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -2251,7 +2251,7 @@ obj_sanity_check() /* monsters temporarily in transit; they should have arrived with hero by the time we get called */ if (mydogs) { - pline("mydogs sanity [not empty]"); + impossible("mydogs sanity [not empty]"); mon_obj_sanity(mydogs, "mydogs minvent sanity"); } @@ -2390,10 +2390,10 @@ struct monst *mon; Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)"); if (mon) monnm = x_monnam(mon, ARTICLE_A, (char *) 0, EXACT_NAME, TRUE); - pline(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj), + impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj), objnm, fmt_ptr((genericptr_t) mon), monnm); } else { - pline(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj), objnm); + impossible(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj), objnm); } } @@ -2421,7 +2421,7 @@ const char *mesg; if (obj->where != OBJ_CONTAINED) insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *) 0); else if (obj->ocontainer != container) - pline("%s obj %s in container %s, not %s", mesg, + impossible("%s obj %s in container %s, not %s", mesg, fmt_ptr((genericptr_t) obj), fmt_ptr((genericptr_t) obj->ocontainer), fmt_ptr((genericptr_t) container)); diff --git a/src/objnam.c b/src/objnam.c index c9d00f6ab..bf108c472 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -2086,6 +2086,7 @@ const char *const *alt_as_is; /* another set like as_is[] */ const struct sing_plur *sp; const char *same, *other, *const *as; int al; + int baselen = strlen(basestr); for (as = as_is; *as; ++as) { al = (int) strlen(*as); @@ -2112,20 +2113,20 @@ const char *const *alt_as_is; /* another set like as_is[] */ } /* skip "ox" -> "oxen" entry when pluralizing "ox" unless it is muskox */ - if (to_plural && strlen(basestr) > 2 && !strcmpi(endstring - 2, "ox") - && strcmpi(endstring - 6, "muskox")) { + if (to_plural && baselen > 2 && !strcmpi(endstring - 2, "ox") + && baselen > 5 && strcmpi(endstring - 6, "muskox")) { /* "fox" -> "foxes" */ Strcasecpy(endstring, "es"); return TRUE; } if (to_plural) { - if (!strcmpi(endstring - 3, "man") + if (baselen > 2 && !strcmpi(endstring - 3, "man") && badman(basestr, to_plural)) { Strcasecpy(endstring, "s"); return TRUE; } } else { - if (!strcmpi(endstring - 3, "men") + if (baselen > 2 && !strcmpi(endstring - 3, "men") && badman(basestr, to_plural)) return TRUE; } diff --git a/src/pline.c b/src/pline.c index 1f604e206..ebde8b145 100644 --- a/src/pline.c +++ b/src/pline.c @@ -1,10 +1,9 @@ -/* NetHack 3.6 pline.c $NHDT-Date: 1520964541 2018/03/13 18:09:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */ +/* NetHack 3.6 pline.c $NHDT-Date: 1541719974 2018/11/08 23:32:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.69 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ -#define NEED_VARARGS /* Uses ... */ /* comment line for pre-compiled headers \ - */ +#define NEED_VARARGS /* Uses ... */ /* comment line for pre-compiled headers */ #include "hack.h" static unsigned pline_flags = 0; @@ -62,7 +61,6 @@ dumplogfreemessages() } #endif -/*VARARGS1*/ /* Note that these declarations rely on knowledge of the internals * of the variable argument handling stuff in "tradstdc.h" */ @@ -70,7 +68,9 @@ dumplogfreemessages() #if defined(USE_STDARG) || defined(USE_VARARGS) static void FDECL(vpline, (const char *, va_list)); -void pline +/*VARARGS1*/ +void +pline VA_DECL(const char *, line) { VA_START(line); @@ -93,7 +93,9 @@ va_list the_args; # define vpline pline -void pline +/*VARARGS1*/ +void +pline VA_DECL(const char *, line) #endif /* USE_STDARG | USE_VARARG */ { /* start of vpline() or of nested block in USE_OLDARG's pline() */ @@ -260,6 +262,7 @@ void You VA_DECL(const char *, line) { char *tmp; + VA_START(line); VA_INIT(line, const char *); vpline(YouMessage(tmp, "You ", line), VA_ARGS); @@ -271,6 +274,7 @@ void Your VA_DECL(const char *, line) { char *tmp; + VA_START(line); VA_INIT(line, const char *); vpline(YouMessage(tmp, "Your ", line), VA_ARGS); @@ -282,6 +286,7 @@ void You_feel VA_DECL(const char *, line) { char *tmp; + VA_START(line); VA_INIT(line, const char *); if (Unaware) @@ -297,6 +302,7 @@ void You_cant VA_DECL(const char *, line) { char *tmp; + VA_START(line); VA_INIT(line, const char *); vpline(YouMessage(tmp, "You can't ", line), VA_ARGS); @@ -308,6 +314,7 @@ void pline_The VA_DECL(const char *, line) { char *tmp; + VA_START(line); VA_INIT(line, const char *); vpline(YouMessage(tmp, "The ", line), VA_ARGS); @@ -319,6 +326,7 @@ void There VA_DECL(const char *, line) { char *tmp; + VA_START(line); VA_INIT(line, const char *); vpline(YouMessage(tmp, "There ", line), VA_ARGS); @@ -444,6 +452,7 @@ void impossible VA_DECL(const char *, s) { char pbuf[2 * BUFSZ]; + VA_START(s); VA_INIT(s, const char *); if (program_state.in_impossible) @@ -453,15 +462,22 @@ VA_DECL(const char *, s) Vsprintf(pbuf, s, VA_ARGS); pbuf[BUFSZ - 1] = '\0'; /* sanity */ paniclog("impossible", pbuf); + if (iflags.debug_fuzzer) + panic("%s", pbuf); pline("%s", VA_PASS1(pbuf)); - pline(VA_PASS1( - "Program in disorder! (Saving and reloading may fix this problem.)")); + /* reuse pbuf[] */ + Strcpy(pbuf, "Program in disorder!"); + if (program_state.something_worth_saving) + Strcat(pbuf, " (Saving and reloading may fix this problem.)"); + pline("%s", VA_PASS1(pbuf)); + program_state.in_impossible = 0; VA_END(); } #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__)) static boolean use_pline_handler = TRUE; + static void execplinehandler(line) const char *line; @@ -499,6 +515,52 @@ const char *line; pline("%s", VA_PASS1("Fork to message handler failed.")); } } -#endif /* defined(POSIX_TYPES) || defined(__GNUC__) */ +#endif /* MSGHANDLER && (POSIX_TYPES || __GNUC__) */ + +/* + * varargs handling for files.c + */ +#if defined(USE_STDARG) || defined(USE_VARARGS) +static void FDECL(vconfig_error_add, (const char *, va_list)); + +/*VARARGS1*/ +void +config_error_add +VA_DECL(const char *, str) +{ + VA_START(str); + VA_INIT(str, char *); + vconfig_error_add(str, VA_ARGS); + VA_END(); +} + +# ifdef USE_STDARG +static void +vconfig_error_add(const char *str, va_list the_args) +# else +static void +vconfig_error_add(str, the_args) +const char *str; +va_list the_args; +# endif + +#else /* !(USE_STDARG || USE_VARARG) => USE_OLDARGS */ + +/*VARARGS1*/ +void +config_error_add +VA_DECL(const char *, str) +#endif /* ?(USE_STDARG || USE_VARARG) */ +{ /* start of vconf...() or of nested block in USE_OLDARG's conf...() */ + char buf[2 * BUFSZ]; + + Vsprintf(buf, str, VA_ARGS); + buf[BUFSZ - 1] = '\0'; + config_erradd(buf); + +#if !(defined(USE_STDARG) || defined(USE_VARARGS)) + VA_END(); /* (see pline/vpline -- ends nested block for USE_OLDARGS) */ +#endif +} /*pline.c*/ diff --git a/src/save.c b/src/save.c index 927798cd9..d7827fcfd 100644 --- a/src/save.c +++ b/src/save.c @@ -77,6 +77,8 @@ static unsigned ustuck_id = 0, usteed_id = 0; int dosave() { + if (iflags.debug_fuzzer) + return 0; clear_nhwindow(WIN_MESSAGE); if (yn("Really save?") == 'n') { clear_nhwindow(WIN_MESSAGE); diff --git a/src/sp_lev.c b/src/sp_lev.c index 5a6f94d0c..242a90e0e 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -3918,9 +3918,9 @@ int n; xchar xx = (xchar) x, yy = (xchar) y; while (n > 0) { + --n; if (xs[n] == xx && ys[n] == yy) return TRUE; - --n; } return FALSE; } diff --git a/src/steed.c b/src/steed.c index 1abdb867c..8cbf9d0ef 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 steed.c $NHDT-Date: 1445906867 2015/10/27 00:47:47 $ $NHDT-Branch: master $:$NHDT-Revision: 1.47 $ */ +/* NetHack 3.6 steed.c $NHDT-Date: 1541806894 2018/11/09 23:41:34 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.54 $ */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -243,6 +243,16 @@ boolean force; /* Quietly force this animal */ pline("I see nobody there."); return (FALSE); } + if (mtmp->data == &mons[PM_LONG_WORM] + && (u.ux + u.dx != mtmp->mx || u.uy + u.dy != mtmp->my)) { + /* 3.6.2: test_move(below) is used to check for trying to mount + diagonally into or out of a doorway or through a tight squeeze; + attempting to mount a tail segment when hero was not adjacent + to worm's head could trigger an impossible() in worm_cross() + called from test_move(), so handle not-on-head before that */ + You("couldn't ride %s, let alone its tail.", a_monnam(mtmp)); + return FALSE; + } if (u.uswallow || u.ustuck || u.utrap || Punished || !test_move(u.ux, u.uy, mtmp->mx - u.ux, mtmp->my - u.uy, TEST_MOVE)) { diff --git a/src/teleport.c b/src/teleport.c index a1adfd95d..9a6ff8f19 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -608,6 +608,8 @@ level_tele() char buf[BUFSZ]; boolean force_dest = FALSE; + if (iflags.debug_fuzzer) + goto random_levtport; if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz)) && !wizard) { You_feel("very disoriented for a moment."); @@ -750,6 +752,8 @@ level_tele() killer.name[0] = 0; /* still alive, so far... */ + if (iflags.debug_fuzzer && newlev < 0) + goto random_levtport; if (newlev < 0 && !force_dest) { if (*u.ushops0) { /* take unpaid inventory items off of shop bills */ diff --git a/src/timeout.c b/src/timeout.c index a469eb116..4c9be0607 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1720,7 +1720,7 @@ timer_sanity_check() struct obj *obj = curr->arg.a_obj; if (obj->timed == 0) { - pline("timer sanity: untimed obj %s, timer %ld", + impossible("timer sanity: untimed obj %s, timer %ld", fmt_ptr((genericptr_t) obj), curr->tid); } } diff --git a/sys/winnt/nttty.c b/sys/winnt/nttty.c index e983d36fb..0409d3336 100644 --- a/sys/winnt/nttty.c +++ b/sys/winnt/nttty.c @@ -433,6 +433,8 @@ tgetch() coord cc; DWORD count; really_move_cursor(); + if (iflags.debug_fuzzer) + return randomkey(); return (program_state.done_hup) ? '\033' : keyboard_handler.pCheckInput( @@ -447,6 +449,8 @@ int *x, *y, *mod; coord cc; DWORD count; really_move_cursor(); + if (iflags.debug_fuzzer) + return randomkey(); ch = (program_state.done_hup) ? '\033' : keyboard_handler.pCheckInput( @@ -704,7 +708,7 @@ cl_eos() void tty_nhbell() { - if (flags.silent) + if (flags.silent || iflags.debug_fuzzer) return; Beep(8000, 500); } @@ -718,6 +722,9 @@ tty_delay_output() clock_t goal; int k; + if (iflags.debug_fuzzer) + return; + goal = 50 + clock(); back_buffer_flip(); while (goal > clock()) { diff --git a/util/makedefs.c b/util/makedefs.c index 19227c3aa..a0ada6731 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -1462,6 +1462,7 @@ char *githash, *gitbranch; havehash = TRUE; } } + free(line); } Fclose(gifp); if (havebranch && havehash) diff --git a/win/tty/termcap.c b/win/tty/termcap.c index 31203811a..5f344f04b 100644 --- a/win/tty/termcap.c +++ b/win/tty/termcap.c @@ -748,6 +748,8 @@ tty_delay_output() #if defined(MICRO) register int i; #endif + if (iflags.debug_fuzzer) + return; #ifdef TIMED_DELAY if (flags.nap) { (void) fflush(stdout); diff --git a/win/tty/topl.c b/win/tty/topl.c index 97919a3d9..5233e1525 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -186,6 +186,8 @@ more() /* avoid recursion -- only happens from interrupts */ if (ttyDisplay->inmore++) return; + if (iflags.debug_fuzzer) + return; if (ttyDisplay->toplin) { tty_curs(BASE_WINDOW, cw->curx + 1, cw->cury); diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 2794331c8..8ebac1267 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -3344,6 +3344,9 @@ tty_nhgetch() */ if (WIN_MESSAGE != WIN_ERR && wins[WIN_MESSAGE]) wins[WIN_MESSAGE]->flags &= ~WIN_STOP; + if (iflags.debug_fuzzer) { + i = randomkey(); + } else { #ifdef UNIX i = (++nesting == 1) ? tgetch() : (read(fileno(stdin), (genericptr_t) &nestbuf, 1) @@ -3352,6 +3355,7 @@ tty_nhgetch() #else i = tgetch(); #endif + } if (!i) i = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */ else if (i == EOF)