Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/indent indent: prevent buffer overflows in 'if (expr...



details:   https://anonhg.NetBSD.org/src/rev/10612e502d4c
branches:  trunk
changeset: 1024660:10612e502d4c
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sat Oct 30 16:18:51 2021 +0000

description:
indent: prevent buffer overflows in 'if (expr) ... stmt'

diffstat:

 usr.bin/indent/indent.c |  85 +++++++++++++++++++++++++++---------------------
 1 files changed, 48 insertions(+), 37 deletions(-)

diffs (174 lines):

diff -r 8f466dc98cc5 -r 10612e502d4c usr.bin/indent/indent.c
--- a/usr.bin/indent/indent.c   Sat Oct 30 15:51:52 2021 +0000
+++ b/usr.bin/indent/indent.c   Sat Oct 30 16:18:51 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: indent.c,v 1.188 2021/10/30 15:26:58 rillig Exp $      */
+/*     $NetBSD: indent.c,v 1.189 2021/10/30 16:18:51 rillig Exp $      */
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
@@ -43,7 +43,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__NetBSD__)
-__RCSID("$NetBSD: indent.c,v 1.188 2021/10/30 15:26:58 rillig Exp $");
+__RCSID("$NetBSD: indent.c,v 1.189 2021/10/30 16:18:51 rillig Exp $");
 #elif defined(__FreeBSD__)
 __FBSDID("$FreeBSD: head/usr.bin/indent/indent.c 340138 2018-11-04 19:24:49Z oshogbo $");
 #endif
@@ -158,6 +158,34 @@
 }
 
 static void
+sc_check_size(size_t n)
+{
+    if ((size_t)(sc_end - sc_buf) + n <= sc_size)
+       return;
+
+    diag(1, "Internal buffer overflow - "
+       "Move big comment from right after if, while, or whatever");
+    fflush(output);
+    exit(1);
+}
+
+static void
+sc_add_char(char ch)
+{
+    sc_check_size(1);
+    *sc_end++ = ch;
+}
+
+static void
+sc_add_range(const char *s, const char *e)
+{
+    size_t len = (size_t)(e - s);
+    sc_check_size(len);
+    memcpy(sc_end, s, len);
+    sc_end += len;
+}
+
+static void
 search_stmt_newline(bool *force_nl)
 {
     if (sc_end == NULL) {
@@ -165,7 +193,7 @@
        save_com[0] = save_com[1] = ' ';
        sc_end = &save_com[2];
     }
-    *sc_end++ = '\n';
+    sc_add_char('\n');
 
     line_no++;
 
@@ -203,23 +231,16 @@
     }
 
     *comment_buffered = true;
-    *sc_end++ = '/';           /* copy in start of comment */
-    *sc_end++ = '*';
+    sc_add_char('/');
+    sc_add_char('*');
 
     for (;;) {                 /* loop until the end of the comment */
-       *sc_end++ = inbuf_next();
-       if (sc_end[-1] == '*' && *inp.s == '/')
-           break;              /* we are at end of comment */
-       if (sc_end >= &save_com[sc_size]) {     /* check for temp buffer
-                                                * overflow */
-           diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
-           fflush(output);
-           exit(1);
+       sc_add_char(inbuf_next());
+       if (sc_end[-1] == '*' && *inp.s == '/') {
+           sc_add_char(inbuf_next());
+           break;
        }
     }
-
-    *sc_end++ = '/';           /* add ending slash */
-    inbuf_skip();              /* get past / in buffer */
 }
 
 static bool
@@ -272,9 +293,8 @@
     if (opt.swallow_optional_blanklines ||
        (!comment_buffered && remove_newlines)) {
        *force_nl = !remove_newlines;
-       while (sc_end > save_com && sc_end[-1] == '\n') {
+       while (sc_end > save_com && sc_end[-1] == '\n')
            sc_end--;
-       }
     }
 
     if (*force_nl) {           /* if we should insert a nl here, put it into
@@ -282,15 +302,14 @@
        *force_nl = false;
        --line_no;              /* this will be re-increased when the newline
                                 * is read from the buffer */
-       *sc_end++ = '\n';
-       *sc_end++ = ' ';
+       sc_add_char('\n');
+       sc_add_char(' ');
        if (opt.verbose)        /* warn if the line was not already broken */
            diag(0, "Line broken");
     }
 
-    /* XXX: buffer overflow? This is essentially a strcpy. */
     for (const char *t_ptr = token.s; *t_ptr != '\0'; ++t_ptr)
-       *sc_end++ = *t_ptr;
+       sc_add_char(*t_ptr);
     return true;
 }
 
@@ -302,7 +321,7 @@
     saved_inp_e = inp.e;
     inp.s = save_com;          /* fix so that subsequent calls to lexi will
                                 * take tokens out of save_com */
-    *sc_end++ = ' ';           /* add trailing blank, just in case */
+    sc_add_char(' ');          /* add trailing blank, just in case */
     inp.e = sc_end;
     sc_end = NULL;
     debug_println("switched inp.s to save_com");
@@ -332,13 +351,8 @@
      * into the buffer so that the later lexi() call will read them.
      */
     if (sc_end != NULL) {
-       while (ch_isblank(*inp.s)) {
-           *sc_end++ = *inp.s++;
-           if (sc_end >= &save_com[sc_size])
-               errx(1, "input too long");
-       }
-       if (inp.s >= inp.e)
-           inbuf_read_line();
+       while (ch_isblank(*inp.s))
+           sc_add_char(inbuf_next());
     }
 
     struct parser_state backup_ps = ps;
@@ -1240,14 +1254,11 @@
            save_com = sc_buf;
            sc_end = save_com;
        } else {
-           *sc_end++ = '\n';   /* add newline between comments */
-           *sc_end++ = ' ';
+           sc_add_char('\n');  /* add newline between comments */
+           sc_add_char(' ');
            --line_no;
        }
-       if (sc_end - save_com + com_end - com_start > sc_size)
-           errx(1, "input too long");
-       memmove(sc_end, lab.s + com_start, (size_t)(com_end - com_start));
-       sc_end += com_end - com_start;
+       sc_add_range(lab.s + com_start, lab.s + com_end);
        lab.e = lab.s + com_start;
        while (lab.e > lab.s && ch_isblank(lab.e[-1]))
            lab.e--;
@@ -1255,7 +1266,7 @@
        saved_inp_e = inp.e;
        inp.s = save_com;       /* fix so that subsequent calls to lexi will
                                 * take tokens out of save_com */
-       *sc_end++ = ' ';        /* add trailing blank, just in case */
+       sc_add_char(' ');       /* add trailing blank, just in case */
        inp.e = sc_end;
        sc_end = NULL;
        debug_println("switched inp.s to save_com");



Home | Main Index | Thread Index | Old Index