]> granicus.if.org Git - nethack/commitdiff
fix pline.c potential buffer overruns
authorPatR <rankin@nethack.org>
Tue, 14 Jan 2020 10:52:34 +0000 (02:52 -0800)
committerPatR <rankin@nethack.org>
Tue, 14 Jan 2020 10:52:34 +0000 (02:52 -0800)
Fix 'Bugs 4, 5, and 6' which all use a similar fix but would have
conflicts over '#define BIGBUFSZ' if committed separately.

Format ("short explanation %s", string_argument), where the
explanation always has modest length but the string is potentially
up to 4*BUFSZ in length, into a 5*BUFSZ buffer.  Then truncate the
result to at most BUFSZ-1 characters so that it can be safely passed
to interface-specific putstr() or raw_print().

Applies to pline(), raw_printf(), and config_error_add().  Also done
for impossible() although there's no evidence that its buffer could
be overflowed in a controlled manner.

doc/fixes36.5
src/pline.c

index a44081a068b2246ed4b8c2d472ffd80e4e1afd86..9085747ab86f341fcc63c185bd41ed8b593f29fa 100644 (file)
@@ -10,6 +10,7 @@ have string_for_opt() return empty_optstr on failure
 ensure existing callers of string_for_opt() check return value before using it
 fix potential buffer overflow in add_menu_coloring()
 fix potential buffer overflow in sym_val()
+fix potential buffer overflow in pline(), raw_printf(), and config_error_add()
 
 
 Fixes to Post-3.6.4 Problems that Were Exposed Via git Repository
index b1ac1dffc856a169c9ed13c4e1f1466ffd19417a..9b5fc31de8eef38b8d30d683f3cd90c8f7c77827 100644 (file)
@@ -6,6 +6,10 @@
 #define NEED_VARARGS /* Uses ... */ /* comment line for pre-compiled headers */
 #include "hack.h"
 
+#define BIGBUFSZ (5 * BUFSZ) /* big enough to format a 4*BUFSZ string (from
+                              * config file parsing) with modest decoration;
+                              * result will then be truncated to BUFSZ-1 */
+
 static unsigned pline_flags = 0;
 static char prevmsg[BUFSZ];
 
@@ -118,7 +122,7 @@ VA_DECL(const char *, line)
 #endif /* USE_STDARG | USE_VARARG */
 {       /* start of vpline() or of nested block in USE_OLDARG's pline() */
     static int in_pline = 0;
-    char pbuf[3 * BUFSZ];
+    char pbuf[BIGBUFSZ]; /* will get chopped down to BUFSZ-1 if longer */
     int ln;
     int msgtyp;
     boolean no_repeat;
@@ -443,15 +447,14 @@ void raw_printf
 VA_DECL(const char *, line)
 #endif
 {
-    char pbuf[3 * BUFSZ];
-    int ln;
+    char pbuf[BIGBUFSZ]; /* will be chopped down to BUFSZ-1 if longer */
     /* Do NOT use VA_START and VA_END in here... see above */
 
     if (index(line, '%')) {
         Vsprintf(pbuf, line, VA_ARGS);
         line = pbuf;
     }
-    if ((ln = (int) strlen(line)) > BUFSZ - 1) {
+    if ((int) strlen(line) > BUFSZ - 1) {
         if (line != pbuf)
             line = strncpy(pbuf, line, BUFSZ - 1);
         /* unlike pline, we don't futz around to keep last few chars */
@@ -470,7 +473,7 @@ VA_DECL(const char *, line)
 void impossible
 VA_DECL(const char *, s)
 {
-    char pbuf[2 * BUFSZ];
+    char pbuf[BIGBUFSZ]; /* will be chopped down to BUFSZ-1 if longer */
 
     VA_START(s);
     VA_INIT(s, const char *);
@@ -571,7 +574,7 @@ config_error_add
 VA_DECL(const char *, str)
 #endif /* ?(USE_STDARG || USE_VARARG) */
 {       /* start of vconf...() or of nested block in USE_OLDARG's conf...() */
-    char buf[2 * BUFSZ];
+    char buf[BIGBUFSZ]; /* will be chopped down to BUFSZ-1 if longer */
 
     Vsprintf(buf, str, VA_ARGS);
     buf[BUFSZ - 1] = '\0';