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 <elia.f.geretto@gmail.com>
master
Benno Schulenberg 2017-01-18 19:53:51 +01:00
parent 94907aa534
commit 9de376deed
2 changed files with 16 additions and 2 deletions

View File

@ -417,6 +417,7 @@ void precalc_multicolorinfo(void)
for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) { for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) {
int startx = 0, nostart = 0; int startx = 0, nostart = 0;
int linelen = strlen(fileptr->data);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno); fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno);
#endif #endif
@ -427,6 +428,9 @@ void precalc_multicolorinfo(void)
/* Look for an end, and start marking how many lines are /* Look for an end, and start marking how many lines are
* encompassed, which should speed up rendering later. */ * encompassed, which should speed up rendering later. */
startx += startmatch.rm_eo; startx += startmatch.rm_eo;
if (startx > linelen)
break;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx); fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx);
#endif #endif

View File

@ -2350,6 +2350,8 @@ void edit_draw(filestruct *fileptr, const char *converted,
for (; varnish != NULL; varnish = varnish->next) { for (; varnish != NULL; varnish = varnish->next) {
size_t index = 0; size_t index = 0;
/* Where in the line we currently begin looking for a match. */ /* 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; int start_col;
/* The starting column of a piece to paint. Zero-based. */ /* The starting column of a piece to paint. Zero-based. */
int paintlen = 0; int paintlen = 0;
@ -2473,6 +2475,8 @@ void edit_draw(filestruct *fileptr, const char *converted,
start_line->multidata[varnish->id] == CSTARTENDHERE)) start_line->multidata[varnish->id] == CSTARTENDHERE))
goto step_two; goto step_two;
linelen = strlen(start_line->data);
/* Now start_line is the first line before fileptr containing /* Now start_line is the first line before fileptr containing
* a start match. Is there a start on that line not followed * a start match. Is there a start on that line not followed
* by an end on that line? */ * by an end on that line? */
@ -2481,7 +2485,8 @@ void edit_draw(filestruct *fileptr, const char *converted,
index += startmatch.rm_eo; index += startmatch.rm_eo;
/* If the start match is zero-length, don't get stuck. */ /* If the start match is zero-length, don't get stuck. */
if (startmatch.rm_so == startmatch.rm_eo) if (startmatch.rm_so == startmatch.rm_eo)
index++; if (++index > linelen)
break;
/* If there is no end after this last start, good. */ /* If there is no end after this last start, good. */
if (regexec(varnish->end, start_line->data + index, 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. */ * looking only after an end match, if there is one. */
index = (paintlen == 0) ? 0 : endmatch.rm_eo; index = (paintlen == 0) ? 0 : endmatch.rm_eo;
linelen = strlen(fileptr->data);
while (regexec(varnish->start, fileptr->data + index, while (regexec(varnish->start, fileptr->data + index,
1, &startmatch, (index == 0) ? 1, &startmatch, (index == 0) ?
0 : REG_NOTBOL) == 0) { 0 : REG_NOTBOL) == 0) {
@ -2574,7 +2581,10 @@ void edit_draw(filestruct *fileptr, const char *converted,
/* Skip over a zero-length match. */ /* Skip over a zero-length match. */
if (endmatch.rm_so == endmatch.rm_eo) if (endmatch.rm_so == endmatch.rm_eo)
index += 1; index += 1;
continue; if (index > linelen)
break;
else
continue;
} }
/* There is no end on this line. But maybe on later lines? */ /* There is no end on this line. But maybe on later lines? */