From 9de376deedf2ff4a96ed89da2e5327788634bbcd Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Wed, 18 Jan 2017 19:53:51 +0100 Subject: [PATCH] painting: stay within the line when skipping zero-length matches Don't blithely overshoot the end of a line when both start regex and end regex match an empty string. Overshooting would let the matching run on into uncharted country and thus ultimately cause a segfault. This fixes https://savannah.gnu.org/bugs/?50056. Reported-by: Elia Geretto --- src/color.c | 4 ++++ src/winio.c | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/color.c b/src/color.c index b89dc903..d4299dfb 100644 --- a/src/color.c +++ b/src/color.c @@ -417,6 +417,7 @@ void precalc_multicolorinfo(void) for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) { int startx = 0, nostart = 0; + int linelen = strlen(fileptr->data); #ifdef DEBUG fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno); #endif @@ -427,6 +428,9 @@ void precalc_multicolorinfo(void) /* Look for an end, and start marking how many lines are * encompassed, which should speed up rendering later. */ startx += startmatch.rm_eo; + + if (startx > linelen) + break; #ifdef DEBUG fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx); #endif diff --git a/src/winio.c b/src/winio.c index 1ba4a861..ae904dcd 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2350,6 +2350,8 @@ void edit_draw(filestruct *fileptr, const char *converted, for (; varnish != NULL; varnish = varnish->next) { size_t index = 0; /* Where in the line we currently begin looking for a match. */ + int linelen; + /* The length of the line we are currently looking at. */ int start_col; /* The starting column of a piece to paint. Zero-based. */ int paintlen = 0; @@ -2473,6 +2475,8 @@ void edit_draw(filestruct *fileptr, const char *converted, start_line->multidata[varnish->id] == CSTARTENDHERE)) goto step_two; + linelen = strlen(start_line->data); + /* Now start_line is the first line before fileptr containing * a start match. Is there a start on that line not followed * by an end on that line? */ @@ -2481,7 +2485,8 @@ void edit_draw(filestruct *fileptr, const char *converted, index += startmatch.rm_eo; /* If the start match is zero-length, don't get stuck. */ if (startmatch.rm_so == startmatch.rm_eo) - index++; + if (++index > linelen) + break; /* If there is no end after this last start, good. */ if (regexec(varnish->end, start_line->data + index, @@ -2534,6 +2539,8 @@ void edit_draw(filestruct *fileptr, const char *converted, * looking only after an end match, if there is one. */ index = (paintlen == 0) ? 0 : endmatch.rm_eo; + linelen = strlen(fileptr->data); + while (regexec(varnish->start, fileptr->data + index, 1, &startmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) { @@ -2574,7 +2581,10 @@ void edit_draw(filestruct *fileptr, const char *converted, /* Skip over a zero-length match. */ if (endmatch.rm_so == endmatch.rm_eo) index += 1; - continue; + if (index > linelen) + break; + else + continue; } /* There is no end on this line. But maybe on later lines? */