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();
 	}

Reply via email to