wresize has a check that the current y/x coordinate (eg, _cury) is <= the new size of the window (eg, _maxy), but this is incorrect since the y/x coordinate is 0-based. As a result, after shrinking a window, if the current coordinates were outside of the new size, a call to PDCurses may attempt to read and write to regions outside the _y array. In the best case, this crashes, but it might also have security implications for some applications.
I have attached a patch that fixes the bug in a clear and simple way, as well as a patch for my own application to workaround the bug (as a reference to other developers).
--- pdcurses/window.c 2013-10-03 05:28:08.000000000 +0000 +++ pdcurses/window.c 2013-10-03 05:28:18.000000000 +0000 @@ -464,8 +464,8 @@ return (WINDOW *)NULL; } - save_curx = min(win->_curx, new->_maxx); - save_cury = min(win->_cury, new->_maxy); + save_curx = min(win->_curx, new->_maxx - 1); + save_cury = min(win->_cury, new->_maxy - 1); if (!(win->_flags & (_SUBPAD|_SUBWIN))) {
commit 71adb9549684ce2424d1c0f5ce6b1d68829c3267 Author: Luke Dashjr <luke-jr+...@utopios.org> Date: Thu Oct 3 06:23:12 2013 +0000 Workaround bug in PDCurses wresize If the current cursor position fell outside the new window dimensions, it would be moved to just-outside - which is still outside We can workaround this by checking if it is outside, and moving it inside if so diff --git a/libblkmaker b/libblkmaker index 19847fb..bca8f6f 160000 --- a/libblkmaker +++ b/libblkmaker @@ -1 +1 @@ -Subproject commit 19847fbab02450fb0db2ae519a35808cdc091991 +Subproject commit bca8f6f5e56c547e9bbc808fb644152e44f3344d diff --git a/miner.c b/miner.c index bd4574f..9d73d4c 100644 --- a/miner.c +++ b/miner.c @@ -2000,6 +2000,28 @@ int my_cancellable_getch(void) return rv; } + +#ifdef PDCURSES +static +int bfg_wresize(WINDOW *win, int lines, int columns) +{ + int rv = wresize(win, lines, columns); + int x, y; + getyx(win, y, x); + if (unlikely(y >= lines || x >= columns)) + { + if (y >= lines) + y = lines - 1; + if (x >= columns) + x = columns - 1; + wmove(win, y, x); + } + return rv; +} +#else +# define bfg_wresize wresize +#endif + #endif void tailsprintf(char *f, const char *fmt, ...) @@ -2359,14 +2381,14 @@ static inline void change_logwinsize(void) statusy = logstart; logcursor = statusy + 1; mvwin(logwin, logcursor, 0); - wresize(statuswin, statusy, x); + bfg_wresize(statuswin, statusy, x); } y -= logcursor; getmaxyx(logwin, logy, logx); /* Detect screen size change */ if (x != logx || y != logy) - wresize(logwin, y, x); + bfg_wresize(logwin, y, x); } static void check_winsizes(void) @@ -2383,10 +2405,10 @@ static void check_winsizes(void) else statusy = logstart; logcursor = statusy + 1; - wresize(statuswin, statusy, x); + bfg_wresize(statuswin, statusy, x); getmaxyx(mainwin, y, x); y -= logcursor; - wresize(logwin, y, x); + bfg_wresize(logwin, y, x); mvwin(logwin, logcursor, 0); unlock_curses(); }