Use a dynamically-allocated line buffer and resize as needed.
authormillert <millert@openbsd.org>
Wed, 27 Sep 2023 21:06:33 +0000 (21:06 +0000)
committermillert <millert@openbsd.org>
Wed, 27 Sep 2023 21:06:33 +0000 (21:06 +0000)
Fixes a buffer overflow for lines over 2048 bytes.
Problem reported by Crystal Kolipe.  OK deraadt@

usr.bin/deroff/deroff.c

index b4b560f..acb33b7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: deroff.c,v 1.17 2023/03/08 04:43:10 guenther Exp $    */
+/*     $OpenBSD: deroff.c,v 1.18 2023/09/27 21:06:33 millert Exp $     */
 
 /*-
  * Copyright (c) 1988, 1993
@@ -135,7 +135,8 @@ int keepblock;      /* keep blocks of text; normally false when msflag */
 
 char chars[128];  /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
 
-char line[LINE_MAX];
+size_t linesz;
+char *line;
 char *lp;
 
 int c;
@@ -342,6 +343,10 @@ main(int ac, char **av)
        files[0] = infile;
        filesp = &files[0];
 
+       linesz = LINE_MAX;
+       if ((line = malloc(linesz)) == NULL)
+               err(1, NULL);
+
        for (i = 'a'; i <= 'z'; ++i)
                chars[i] = LETTER;
        for (i = 'A'; i <= 'Z'; ++i)
@@ -477,7 +482,15 @@ regline(void (*pfunc)(char *, int), int constant)
 
        line[0] = c;
        lp = line;
-       while (lp - line < sizeof(line)) {
+       for (;;) {
+               if (lp - line == linesz - 1) {
+                       char *newline = reallocarray(line, linesz, 2);
+                       if (newline == NULL)
+                               err(1, NULL);
+                       lp = newline + (lp - line);
+                       line = newline;
+                       linesz *= 2;
+               }
                if (c == '\\') {
                        *lp = ' ';
                        backsl();