@@ -174,6 +174,11 @@ qf_init(
174174 qf_title );
175175}
176176
177+ /*
178+ * Maximum number of bytes allowed per line while reading a errorfile.
179+ */
180+ #define LINE_MAXLEN 4096
181+
177182/*
178183 * Read the errorfile "efile" into memory, line by line, building the error
179184 * list.
@@ -197,8 +202,15 @@ qf_init_ext(
197202{
198203 char_u * namebuf ;
199204 char_u * errmsg ;
205+ int errmsglen ;
200206 char_u * pattern ;
201207 char_u * fmtstr = NULL ;
208+ char_u * growbuf = NULL ;
209+ int growbuflen ;
210+ int growbufsiz ;
211+ char_u * linebuf ;
212+ int linelen ;
213+ int discard ;
202214 int col = 0 ;
203215 char_u use_viscol = FALSE;
204216 int type = 0 ;
@@ -227,6 +239,7 @@ qf_init_ext(
227239 char_u * directory = NULL ;
228240 char_u * currfile = NULL ;
229241 char_u * tail = NULL ;
242+ char_u * p_buf = NULL ;
230243 char_u * p_str = NULL ;
231244 listitem_T * p_li = NULL ;
232245 struct dir_stack_T * file_stack = NULL ;
@@ -250,7 +263,8 @@ qf_init_ext(
250263 };
251264
252265 namebuf = alloc_id (CMDBUFFSIZE + 1 , aid_qf_namebuf );
253- errmsg = alloc_id (CMDBUFFSIZE + 1 , aid_qf_errmsg );
266+ errmsglen = CMDBUFFSIZE + 1 ;
267+ errmsg = alloc_id (errmsglen , aid_qf_errmsg );
254268 pattern = alloc_id (CMDBUFFSIZE + 1 , aid_qf_pattern );
255269 if (namebuf == NULL || errmsg == NULL || pattern == NULL )
256270 goto qf_init_end ;
@@ -513,37 +527,87 @@ qf_init_ext(
513527 /* Get the next line from the supplied string */
514528 char_u * p ;
515529
516- if (! * p_str ) /* Reached the end of the string */
530+ if (* p_str == NUL ) /* Reached the end of the string */
517531 break ;
518532
519533 p = vim_strchr (p_str , '\n' );
520- if (p )
521- len = (int )(p - p_str + 1 ) ;
534+ if (p != NULL )
535+ len = (int )(p - p_str ) + 1 ;
522536 else
523537 len = (int )STRLEN (p_str );
524538
525- if (len > CMDBUFFSIZE - 2 )
526- vim_strncpy (IObuff , p_str , CMDBUFFSIZE - 2 );
539+ if (len > IOSIZE - 2 )
540+ {
541+ /*
542+ * If the line exceeds LINE_MAXLEN exclude the last
543+ * byte since it's not a NL character.
544+ */
545+ linelen = len > LINE_MAXLEN ? LINE_MAXLEN - 1 : len ;
546+ if (growbuf == NULL )
547+ {
548+ growbuf = alloc (linelen );
549+ growbufsiz = linelen ;
550+ }
551+ else if (linelen > growbufsiz )
552+ {
553+ growbuf = vim_realloc (growbuf , linelen );
554+ if (growbuf == NULL )
555+ goto qf_init_end ;
556+ growbufsiz = linelen ;
557+ }
558+ linebuf = growbuf ;
559+ }
527560 else
528- vim_strncpy (IObuff , p_str , len );
561+ {
562+ linebuf = IObuff ;
563+ linelen = len ;
564+ }
565+ vim_strncpy (linebuf , p_str , linelen );
529566
567+ /*
568+ * Increment using len in order to discard the rest of the
569+ * line if it exceeds LINE_MAXLEN.
570+ */
530571 p_str += len ;
531572 }
532573 else if (tv -> v_type == VAR_LIST )
533574 {
534575 /* Get the next line from the supplied list */
535- while (p_li && (p_li -> li_tv .v_type != VAR_STRING
536- || p_li -> li_tv .vval .v_string == NULL ))
576+ while (p_li != NULL
577+ && (p_li -> li_tv .v_type != VAR_STRING
578+ || p_li -> li_tv .vval .v_string == NULL ))
537579 p_li = p_li -> li_next ; /* Skip non-string items */
538580
539- if (! p_li ) /* End of the list */
581+ if (p_li == NULL ) /* End of the list */
540582 break ;
541583
542584 len = (int )STRLEN (p_li -> li_tv .vval .v_string );
543- if (len > CMDBUFFSIZE - 2 )
544- len = CMDBUFFSIZE - 2 ;
585+ if (len > IOSIZE - 2 )
586+ {
587+ linelen = len ;
588+ if (linelen > LINE_MAXLEN )
589+ linelen = LINE_MAXLEN - 1 ;
590+ if (growbuf == NULL )
591+ {
592+ growbuf = alloc (linelen );
593+ growbufsiz = linelen ;
594+ }
595+ else if (linelen > growbufsiz )
596+ {
597+ if ((growbuf = vim_realloc (growbuf ,
598+ linelen )) == NULL )
599+ goto qf_init_end ;
600+ growbufsiz = linelen ;
601+ }
602+ linebuf = growbuf ;
603+ }
604+ else
605+ {
606+ linebuf = IObuff ;
607+ linelen = len ;
608+ }
545609
546- vim_strncpy (IObuff , p_li -> li_tv .vval .v_string , len );
610+ vim_strncpy (linebuf , p_li -> li_tv .vval .v_string , linelen );
547611
548612 p_li = p_li -> li_next ; /* next item */
549613 }
@@ -553,23 +617,118 @@ qf_init_ext(
553617 /* Get the next line from the supplied buffer */
554618 if (buflnum > lnumlast )
555619 break ;
556- vim_strncpy (IObuff , ml_get_buf (buf , buflnum ++ , FALSE),
557- CMDBUFFSIZE - 2 );
620+ p_buf = ml_get_buf (buf , buflnum ++ , FALSE);
621+ linelen = (int )STRLEN (p_buf );
622+ if (linelen > IOSIZE - 2 )
623+ {
624+ if (growbuf == NULL )
625+ {
626+ growbuf = alloc (linelen );
627+ growbufsiz = linelen ;
628+ }
629+ else if (linelen > growbufsiz )
630+ {
631+ if (linelen > LINE_MAXLEN )
632+ linelen = LINE_MAXLEN - 1 ;
633+ if ((growbuf = vim_realloc (growbuf , linelen )) == NULL )
634+ goto qf_init_end ;
635+ growbufsiz = linelen ;
636+ }
637+ linebuf = growbuf ;
638+ }
639+ else
640+ linebuf = IObuff ;
641+ vim_strncpy (linebuf , p_buf , linelen );
558642 }
559643 }
560- else if (fgets ((char * )IObuff , CMDBUFFSIZE - 2 , fd ) == NULL )
561- break ;
644+ else
645+ {
646+ if (fgets ((char * )IObuff , IOSIZE , fd ) == NULL )
647+ break ;
562648
563- IObuff [CMDBUFFSIZE - 2 ] = NUL ; /* for very long lines */
564- #ifdef FEAT_MBYTE
565- remove_bom (IObuff );
649+ discard = FALSE;
650+ linelen = (int )STRLEN (IObuff );
651+ if (linelen == IOSIZE - 1 && (IObuff [linelen - 1 ] != '\n'
652+ #ifdef USE_CRNL
653+ || IObuff [linelen - 1 ] != '\r'
654+ #endif
655+ ))
656+ {
657+ /*
658+ * The current line exceeds IObuff, continue reading using
659+ * growbuf until EOL or LINE_MAXLEN bytes is read.
660+ */
661+ if (growbuf == NULL )
662+ {
663+ growbufsiz = 2 * (IOSIZE - 1 );
664+ growbuf = alloc (growbufsiz );
665+ if (growbuf == NULL )
666+ goto qf_init_end ;
667+ }
668+
669+ /* Copy the read part of the line, excluding null-terminator */
670+ memcpy (growbuf , IObuff , IOSIZE - 1 );
671+ growbuflen = linelen ;
672+
673+ for (;;)
674+ {
675+ if (fgets ((char * )growbuf + growbuflen ,
676+ growbufsiz - growbuflen , fd ) == NULL )
677+ break ;
678+ linelen = STRLEN (growbuf + growbuflen );
679+ growbuflen += linelen ;
680+ if (growbuf [growbuflen - 1 ] == '\n'
681+ #ifdef USE_CRNL
682+ || growbuf [growbuflen - 1 ] == '\r'
683+ #endif
684+ )
685+ break ;
686+ if (growbufsiz == LINE_MAXLEN )
687+ {
688+ discard = TRUE;
689+ break ;
690+ }
691+
692+ growbufsiz = 2 * growbufsiz < LINE_MAXLEN
693+ ? 2 * growbufsiz : LINE_MAXLEN ;
694+ growbuf = vim_realloc (growbuf , 2 * growbufsiz );
695+ if (growbuf == NULL )
696+ goto qf_init_end ;
697+ }
698+
699+ while (discard )
700+ {
701+ /*
702+ * The current line is longer than LINE_MAXLEN, continue
703+ * reading but discard everything until EOL or EOF is
704+ * reached.
705+ */
706+ if (fgets ((char * )IObuff , IOSIZE , fd ) == NULL
707+ || (int )STRLEN (IObuff ) < IOSIZE - 1
708+ || IObuff [IOSIZE - 1 ] == '\n'
709+ #ifdef USE_CRNL
710+ || IObuff [IOSIZE - 1 ] == '\r'
566711#endif
712+ )
713+ break ;
714+ }
715+
716+ linebuf = growbuf ;
717+ linelen = growbuflen ;
718+ }
719+ else
720+ linebuf = IObuff ;
721+ }
567722
568- if (( efmp = vim_strrchr ( IObuff , '\n' )) != NULL )
569- * efmp = NUL ;
723+ if (linelen > 0 && linebuf [ linelen - 1 ] == '\n' )
724+ linebuf [ linelen - 1 ] = NUL ;
570725#ifdef USE_CRNL
571- if ((efmp = vim_strrchr (IObuff , '\r' )) != NULL )
572- * efmp = NUL ;
726+ if (linelen > 0 && linebuf [linelen - 1 ] == '\r' )
727+ linebuf [linelen - 1 ] = NUL ;
728+ #endif
729+
730+ #ifdef FEAT_MBYTE
731+ remove_bom (linebuf );
573732#endif
574733
575734 /* If there was no %> item start at the first pattern */
@@ -606,7 +765,7 @@ qf_init_ext(
606765 tail = NULL ;
607766
608767 regmatch .regprog = fmt_ptr -> prog ;
609- r = vim_regexec (& regmatch , IObuff , (colnr_T )0 );
768+ r = vim_regexec (& regmatch , linebuf , (colnr_T )0 );
610769 fmt_ptr -> prog = regmatch .regprog ;
611770 if (r )
612771 {
@@ -663,12 +822,27 @@ qf_init_ext(
663822 type = * regmatch .startp [i ];
664823 }
665824 if (fmt_ptr -> flags == '+' && !multiscan ) /* %+ */
666- STRCPY (errmsg , IObuff );
825+ {
826+ if (linelen > errmsglen ) {
827+ /* linelen + null terminator */
828+ if ((errmsg = vim_realloc (errmsg , linelen + 1 )) == NULL )
829+ goto qf_init_end ;
830+ errmsglen = linelen + 1 ;
831+ }
832+ vim_strncpy (errmsg , linebuf , linelen );
833+ }
667834 else if ((i = (int )fmt_ptr -> addr [5 ]) > 0 ) /* %m */
668835 {
669836 if (regmatch .startp [i ] == NULL || regmatch .endp [i ] == NULL )
670837 continue ;
671838 len = (int )(regmatch .endp [i ] - regmatch .startp [i ]);
839+ if (len > errmsglen ) {
840+ /* len + null terminator */
841+ if ((errmsg = vim_realloc (errmsg , len + 1 ))
842+ == NULL )
843+ goto qf_init_end ;
844+ errmsglen = len + 1 ;
845+ }
672846 vim_strncpy (errmsg , regmatch .startp [i ], len );
673847 }
674848 if ((i = (int )fmt_ptr -> addr [6 ]) > 0 ) /* %r */
@@ -742,7 +916,14 @@ qf_init_ext(
742916 namebuf [0 ] = NUL ; /* no match found, remove file name */
743917 lnum = 0 ; /* don't jump to this line */
744918 valid = FALSE;
745- STRCPY (errmsg , IObuff ); /* copy whole line to error message */
919+ if (linelen > errmsglen ) {
920+ /* linelen + null terminator */
921+ if ((errmsg = vim_realloc (errmsg , linelen + 1 )) == NULL )
922+ goto qf_init_end ;
923+ errmsglen = linelen + 1 ;
924+ }
925+ /* copy whole line to error message */
926+ vim_strncpy (errmsg , linebuf , linelen );
746927 if (fmt_ptr == NULL )
747928 multiline = multiignore = FALSE;
748929 }
@@ -878,6 +1059,7 @@ qf_init_ext(
8781059 vim_free (errmsg );
8791060 vim_free (pattern );
8801061 vim_free (fmtstr );
1062+ vim_free (growbuf );
8811063
8821064#ifdef FEAT_WINDOWS
8831065 qf_update_buffer (qi , TRUE);
0 commit comments