]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
ccfilter: buffer overflow in ccfilter.c with crafted compiler output
authorHirohito Higashi <h.east.727@gmail.com>
Thu, 18 Jun 2026 20:12:48 +0000 (20:12 +0000)
committerChristian Brabandt <cb@256bit.org>
Thu, 18 Jun 2026 20:12:48 +0000 (20:12 +0000)
Problem:  ccfilter: can overflow fixed-size buffers (FileName, BasePath,
          Reason) when parsing crafted compiler output, because the
          sscanf() calls read "%[" fields without a width limit (DDugs)
Solution: Give every sscanf() "%[" conversion a width limit derived from
          the buffer size (Hirohito Higashi).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/tools/ccfilter.c
runtime/tools/ccfilter_README.txt

index 269e4ee662893120feabff789db8287a89ada7b0..5fe6307bf8cba7d52e07cb2ec75f233503dfc3c8 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-#define LINELENGTH 2048
+/*
+ * sscanf() needs a literal field width on each "%[", so define the widths
+ * once and derive the buffer sizes (width + 1) and format widths (via STR()).
+ */
+#define STR_(x) #x
+#define STR(x) STR_(x)
+#define LINEWIDTH  2047
+#define LINELENGTH (LINEWIDTH + 1)
+#define PATHWIDTH  1023
+#define PATHLENGTH (PATHWIDTH + 1)
 
 /* Collector(s) */
 char          Line[LINELENGTH];
 char          Line2[LINELENGTH];
 /* Components */
-char          FileName[1024];
-char          BasePath[1024];
-char          CWD[1024];
+char          FileName[PATHLENGTH];
+char          BasePath[PATHLENGTH];
+char          CWD[PATHLENGTH];
 unsigned long  Row;
 unsigned long  Col;
 char          Severity;
@@ -184,7 +193,7 @@ int main( int argc, char *argv[] )
          case COMPILER_GCC:
            Severity = 'e';
 #ifdef GOTO_FROM_WHERE_INCLUDED
-           rv = sscanf( Line, "In file included from %[^:]:%lu:",
+           rv = sscanf( Line, "In file included from %" STR(PATHWIDTH) "[^:]:%lu:",
                               FileName, &Row );
            if ( rv == 2 )
              {
@@ -193,11 +202,11 @@ int main( int argc, char *argv[] )
            else
 #endif
              {
-               if ((rv = sscanf( Line, "%[^:]:%lu: warning: %[^\n]",
+               if ((rv = sscanf( Line, "%" STR(PATHWIDTH) "[^:]:%lu: warning: %" STR(LINEWIDTH) "[^\n]",
                                   FileName, &Row, Reason ))==3) {
                 Severity = 'w';
                } else {
-               rv = sscanf( Line, "%[^:]:%lu: %[^\n]",
+               rv = sscanf( Line, "%" STR(PATHWIDTH) "[^:]:%lu: %" STR(LINEWIDTH) "[^\n]",
                                   FileName, &Row, Reason );
                }
                ok = ( rv == 3 );
@@ -205,24 +214,24 @@ int main( int argc, char *argv[] )
            Col = (dec_col ? 1 : 0 );
            break;
          case COMPILER_AIX:
-           rv = sscanf( Line, "\"%[^\"]\", line %lu.%lu: %*s (%c) %[^\n]",
+           rv = sscanf( Line, "\"%" STR(PATHWIDTH) "[^\"]\", line %lu.%lu: %*s (%c) %" STR(LINEWIDTH) "[^\n]",
                               FileName, &Row, &Col, &Severity, Reason );
            ok = ( rv == 5 );
            break;
          case COMPILER_HPUX:
-           rv = sscanf( Line, "cc: \"%[^\"]\", line %lu: %c%*[^:]: %[^\n]",
+           rv = sscanf( Line, "cc: \"%" STR(PATHWIDTH) "[^\"]\", line %lu: %c%*[^:]: %" STR(LINEWIDTH) "[^\n]",
                               FileName, &Row, &Severity, Reason );
            ok = ( rv == 4 );
            Col = (dec_col ? 1 : 0 );
            break;
          case COMPILER_SOLARIS:
-           rv = sscanf( Line, "\"%[^\"]\", line %lu: warning: %[^\n]",
+           rv = sscanf( Line, "\"%" STR(PATHWIDTH) "[^\"]\", line %lu: warning: %" STR(LINEWIDTH) "[^\n]",
                               FileName, &Row, Reason );
            Severity = 'w';
            ok = ( rv == 3 );
            if ( rv != 3 )
              {
-               rv = sscanf( Line, "\"%[^\"]\", line %lu: %[^\n]",
+               rv = sscanf( Line, "\"%" STR(PATHWIDTH) "[^\"]\", line %lu: %" STR(LINEWIDTH) "[^\n]",
                                   FileName, &Row, Reason );
                Severity = 'e';
                ok = ( rv == 3 );
@@ -230,18 +239,18 @@ int main( int argc, char *argv[] )
            Col = (dec_col ? 1 : 0 );
            break;
          case COMPILER_ATT:
-           rv   = sscanf( Line, "%c \"%[^\"]\",L%lu/C%lu%*[^:]:%[^\n]",
+           rv   = sscanf( Line, "%c \"%" STR(PATHWIDTH) "[^\"]\",L%lu/C%lu%*[^:]:%" STR(LINEWIDTH) "[^\n]",
                                 &Severity, FileName, &Row, &Col, Reason );
            ok = ( rv == 5 );
 
            if (rv != 5)
-             { rv   = sscanf( Line, "%c \"%[^\"]\",L%lu/C%lu: %[^\n]",
+             { rv   = sscanf( Line, "%c \"%" STR(PATHWIDTH) "[^\"]\",L%lu/C%lu: %" STR(LINEWIDTH) "[^\n]",
                                     &Severity, FileName, &Row, &Col, Reason );
                ok = ( rv == 5 );
              }
 
            if (rv != 5)
-             { rv  = sscanf( Line, "%c \"%[^\"]\",L%lu: %[^\n]",
+             { rv  = sscanf( Line, "%c \"%" STR(PATHWIDTH) "[^\"]\",L%lu: %" STR(LINEWIDTH) "[^\n]",
                                   &Severity, FileName, &Row, Reason );
                ok = ( rv == 4 );
                Col = (dec_col ? 1 : 0 );
@@ -273,10 +282,10 @@ int main( int argc, char *argv[] )
                  }
                 else
                  {
-                   rv = sscanf( p+2, "%[^:]: %lu: %[^\n]",
+                   rv = sscanf( p+2, "%" STR(PATHWIDTH) "[^:]: %lu: %" STR(LINEWIDTH) "[^\n]",
                                 FileName, &Row, Reason );
                    if (rv != 3)
-                     rv = sscanf( p+2, "%[^,], line %lu: %[^\n]",
+                     rv = sscanf( p+2, "%" STR(PATHWIDTH) "[^,], line %lu: %" STR(LINEWIDTH) "[^\n]",
                                   FileName, &Row, Reason );
                    ok = ( rv == 3 );
                  }
@@ -307,7 +316,7 @@ int main( int argc, char *argv[] )
              p = &Line[1];
          else
              p = &Line[0];
-         ok = sscanf( p, "make[%*d]: Entering directory `%[^']",
+         ok = sscanf( p, "make[%*d]: Entering directory `%" STR(PATHWIDTH) "[^']",
                       BasePath );
          if (verbose)
            printf( "[%u]?%s\n", (unsigned)ok, Line );
index ea989f2574129b8ed486e6b3f5d302ee06232016..70d8f3f4d2601012a99ce000240adb54746d4db2 100644 (file)
@@ -5,7 +5,8 @@ ccfilter is a C program to filter the output of a few compilers to a common
 QuickFix format.  It is provided with Vim to make quickfix useful for more
 compilers.
 
-ccfilter WILL FAIL with long lines (more than 2047 bytes).
+ccfilter handles input lines up to 2047 bytes; longer lines are split and
+may not be parsed correctly.
 
 
 COMPILING AND INSTALLING: