]> granicus.if.org Git - nethack/commitdiff
Fuzz testing debug tool
authorPasi Kallinen <paxed@alt.org>
Thu, 8 Nov 2018 13:50:53 +0000 (15:50 +0200)
committerPasi Kallinen <paxed@alt.org>
Thu, 8 Nov 2018 13:55:49 +0000 (15:55 +0200)
Add code to run a fuzz tester, simulating (more-or-less) random
keyboard mashing. There's no option to turn it on, you need to
set iflags.debug_fuzzer on via a debugger or something along
those lines.

14 files changed:
include/extern.h
include/flag.h
src/allmain.c
src/cmd.c
src/do.c
src/end.c
src/mail.c
src/pline.c
src/save.c
src/teleport.c
sys/winnt/nttty.c
win/tty/termcap.c
win/tty/topl.c
win/tty/wintty.c

index 8887994bb7f37237b19905b72ad277c0d0b0e16e..5d82cf32418678f5a87ce46b29153f9bb0cee16d 100644 (file)
@@ -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((*))));
index 58cda783814c2ce6e4df442f22594094dd0ae9af..b8c6a5993839f60b220524745dca76b5b804b9ed 100644 (file)
@@ -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 ' '? */
index 39f38e1f74002ee78096461aefc1c4777ed4039a..9c76b2c00c81752b0be42688c024fd594e11e8b2 100644 (file)
@@ -389,7 +389,7 @@ boolean resuming;
             continue;
         }
 
-        if (iflags.sanity_check)
+        if (iflags.sanity_check || iflags.debug_fuzzer)
             sanity_check();
 
 #ifdef CLIPPING
index 52766a773a8d080a4038615a25d91b681083035e..c783a5b2e1fcc355e8e36931e04575eb3b24f590 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -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;
@@ -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
index a403376b7d558f8e5ef9dde201d15ef7b2f6658a..bcae4ca4382271ff7fb83e2bc6d133d531ab551d 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1061,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;
     }
index c423fbcde56c9ea1242e6a6d03b02d274e015f02..9cd4d40a082dff16990f4959f6cdf720e2e28a22 100644 (file)
--- 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 */
index 067dab09f89cf0308b1af72c50ff69f8204c899e..3f47e3a55adc23bb8d0e6455ec804f899976c9e8 100644 (file)
@@ -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;
 
index 1f604e20645d0c8ef8c13f6f647e87f10cdb427d..e88eea5cf02e03fa66e9084c3169ed21b80fec28 100644 (file)
@@ -453,6 +453,8 @@ VA_DECL(const char *, s)
     Vsprintf(pbuf, s, VA_ARGS);
     pbuf[BUFSZ - 1] = '\0'; /* sanity */
     paniclog("impossible", pbuf);
+    if (iflags.debug_fuzzer)
+        panic(pbuf);
     pline("%s", VA_PASS1(pbuf));
     pline(VA_PASS1(
        "Program in disorder!  (Saving and reloading may fix this problem.)"));
index 927798cd94395471cf54e11b5b63949163970ab1..d7827fcfd8b487ea092eab489b3a7c854fd47315 100644 (file)
@@ -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);
index a1adfd95dc859e7b8c86711c50a192cffb5ebd91..9a6ff8f19ac052c660632976b51832e46bf0f26d 100644 (file)
@@ -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 */
index e983d36fbcac28ced8dcd00bbfc1f592bd004e5e..0409d333650c6c8213bd97ea503081bcd1d8b19a 100644 (file)
@@ -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()) {
index 31203811a35f6d22f33c0a30855d175542c020b1..5f344f04b144cb53f816809c198273e7a67a3a6b 100644 (file)
@@ -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);
index 97919a3d99432e145cfa3e04f5b32f5d56444db2..5233e1525e0198803786753c6320dc28eb399442 100644 (file)
@@ -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);
index 2794331c806d146c4dd7c81ca72af3a7aeb5eaad..8ebac1267870f30c3b9fab9f873395213b6ea23e 100644 (file)
@@ -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)