]> granicus.if.org Git - nethack/commitdiff
Fixed bug with inmore and toplin state management.
authorBart House <bart@barthouse.com>
Fri, 12 Jul 2019 04:04:29 +0000 (21:04 -0700)
committerBart House <bart@barthouse.com>
Fri, 12 Jul 2019 04:17:46 +0000 (21:17 -0700)
When fuzzing, we would increment ttyDisplay->inmore but then prematurely
exit more() leaving ttyDisplay->inmore set.

Under various conditions, we can request to remember the topline when
the topline had not yet been acknowledged leaving toplin state in an
inappropriate state.

win/tty/topl.c

index d2a889cc97e7174353f10ffe2fece2665b36e99a..bb79be26c060aaa41e54ad1f05d428a8b4ea6717 100644 (file)
@@ -139,7 +139,7 @@ const char *str;
     putsyms(str);
     cl_end();
     ttyDisplay->toplin = TOPLINE_NEED_MORE;
-    if (ttyDisplay->cury && otoplin != 3)
+    if (ttyDisplay->cury && otoplin != TOPLINE_SPECIAL_PROMPT)
         more();
 }
 
@@ -204,12 +204,15 @@ more()
 {
     struct WinDesc *cw = wins[WIN_MESSAGE];
 
-    /* avoid recursion -- only happens from interrupts */
-    if (ttyDisplay->inmore++)
-        return;
     if (iflags.debug_fuzzer)
         return;
 
+    /* avoid recursion -- only happens from interrupts */
+    if (ttyDisplay->inmore)
+        return;
+
+    ttyDisplay->inmore++;
+
     if (ttyDisplay->toplin) {
         tty_curs(BASE_WINDOW, cw->curx + 1, cw->cury);
         if (cw->curx >= CO - 8)
@@ -256,6 +259,7 @@ register const char *bp;
         && cw->cury == 0
         && n0 + (int) strlen(toplines) + 3 < CO - 8 /* room for --More-- */
         && (notdied = strncmp(bp, "You die", 7)) != 0) {
+        nhassert(strlen(toplines) == cw->curx);
         Strcat(toplines, "  ");
         Strcat(toplines, bp);
         cw->curx += 2;
@@ -309,6 +313,7 @@ char c;
         if (ttyDisplay->curx == 0 && ttyDisplay->cury > 0)
             tty_curs(BASE_WINDOW, CO, (int) ttyDisplay->cury - 1);
         backsp();
+        nhassert(ttyDisplay->curx > 0);
         ttyDisplay->curx--;
         cw->curx = ttyDisplay->curx;
         return;
@@ -689,6 +694,13 @@ boolean restoring_msghist;
     }
 
     if (msg) {
+        /* Caller is asking us to remember a top line that needed more.
+           Should we call more?  This can happen when the player has set
+           iflags.force_invmenu and they attempt to shoot with nothing in
+           the quiver. */
+        if (ttyDisplay && ttyDisplay->toplin == TOPLINE_NEED_MORE)
+            ttyDisplay->toplin = TOPLINE_NON_EMPTY;
+
         /* move most recent message to history, make this become most recent */
         remember_topl();
         Strcpy(toplines, msg);
@@ -696,6 +708,9 @@ boolean restoring_msghist;
         dumplogmsg(toplines);
 #endif
     } else if (snapshot_mesgs) {
+        nhassert(ttyDisplay == NULL ||
+                 ttyDisplay->toplin != TOPLINE_NEED_MORE);
+
         /* done putting arbitrary messages in; put the snapshot ones back */
         for (idx = 0; snapshot_mesgs[idx]; ++idx) {
             remember_topl();