From 6bd2f4979cb9397b3207d87a4a7d69d8578b1241 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 25 May 2019 07:37:08 -0700 Subject: [PATCH] curses memory leak Back in February, my e991dd1b0c4192495c7e9092c10fa83bb6d81a24 added ESC (when there's no input) as an early return for curses' getline, but it neglected to clean up some allocated memory. --- doc/fixes36.3 | 3 ++- win/curses/cursmesg.c | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 28564e3da..5ad8f325d 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.15 $ $NHDT-Date: 1558686805 2019/05/24 08:33:25 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.18 $ $NHDT-Date: 1558794988 2019/05/25 14:36:28 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -47,6 +47,7 @@ curses: when display windows get reconfigured (after setting align_status, messages rather than most recent N. [Still room for improvement; when feasible it combines short lines, resulting in N messages on fewer than N lines and leaving some of the available lines blank.] +curses: plug memory leak when getting a line of input is cancelled by ESC tty: re-do one optimization used when status conditions have all been removed and remove another that tried to check whether condition text to be displayed next was the same as the existing value; sometimes new diff --git a/win/curses/cursmesg.c b/win/curses/cursmesg.c index 0d67cff1c..13c3109ba 100644 --- a/win/curses/cursmesg.c +++ b/win/curses/cursmesg.c @@ -86,7 +86,7 @@ curses_message_win_puts(const char *message, boolean recursed) scroll_window(MESSAGE_WIN); mx = width; my--; - strcpy(toplines, message); + Strcpy(toplines, message); } return; } @@ -466,10 +466,10 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) char *tmpstr; /* for free() */ int maxy, maxx; /* linewrap / scroll */ int ch; - WINDOW *win = curses_get_nhwin(MESSAGE_WIN); int border_space = 0; int len; /* of answer string */ boolean border = curses_window_has_border(MESSAGE_WIN); + WINDOW *win = curses_get_nhwin(MESSAGE_WIN); orig_cursor = curs_set(0); @@ -485,6 +485,7 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) maxy = height - 1 + border_space; maxx = width - 1 + border_space; + /* +2? buffer already includes room for terminator; +1: "prompt answer" */ tmpbuf = (char *) alloc((unsigned) ((int) strlen(prompt) + buffer + 2)); maxlines = buffer / width * 2; Strcpy(tmpbuf, prompt); @@ -585,7 +586,7 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) /* if there isn't any input yet, return ESC */ if (len == 0) { Strcpy(answer, "\033"); - return; + goto alldone; } /* otherwise, discard current input and start over; first need to blank it from the screen */ @@ -609,27 +610,19 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) break; case ERR: /* should not happen */ *answer = '\0'; - free(tmpbuf); - free(linestarts); - curs_set(orig_cursor); - curses_toggle_color_attr(win, NONE, A_BOLD, OFF); - return; + goto alldone; case '\r': case '\n': - free(linestarts); (void) strncpy(answer, p_answer, buffer); answer[buffer - 1] = '\0'; Strcpy(toplines, tmpbuf); mesg_add_line(tmpbuf); - free(tmpbuf); - curs_set(orig_cursor); - curses_toggle_color_attr(win, NONE, A_BOLD, OFF); if (++my > maxy) { scroll_window(MESSAGE_WIN); my--; } mx = border_space; - return; + goto alldone; case '\177': /* DEL/Rubout */ case KEY_DC: /* delete-character */ case '\b': /* ^H (Backspace: '\011') */ @@ -666,6 +659,13 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) p_answer[len] = '\0'; } } + + alldone: + free(linestarts); + free(tmpbuf); + curses_toggle_color_attr(win, NONE, A_BOLD, OFF); + curs_set(orig_cursor); + return; } /* Scroll lines upward in given window, or clear window if only one line. */