From 9de376deedf2ff4a96ed89da2e5327788634bbcd Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@justemail.net>
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 <elia.f.geretto@gmail.com>
---
 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? */
-- 
GitLab