in edit_draw(), properly ignore zero-length regexes in multi-line

regexes as well as single-line ones; this avoids a segfault when trying
to color e.g. "start="$" end="$""


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@3484 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
David Lawrence Ramsey 2006-05-08 15:57:04 +00:00
parent c7b9e15e9a
commit a5f833de42
2 changed files with 110 additions and 99 deletions

View File

@ -198,6 +198,11 @@ CVS code -
- Add Ctrl-/ as an alias for Ctrl-_. (DLR, found by Benno - Add Ctrl-/ as an alias for Ctrl-_. (DLR, found by Benno
Schulenberg) Schulenberg)
- Simplify the if blocks wherever possible. (DLR) - Simplify the if blocks wherever possible. (DLR)
edit_draw()
- Properly ignore zero-length regexes in multi-line regexes as
well as single-line ones. This avoids a segfault when trying
to color e.g. "start="$" end="$"". (DLR, found by Trevor
Caira)
- configure.ac: - configure.ac:
- Remove old warnings about color support. (DLR) - Remove old warnings about color support. (DLR)
- doc/faq.html: - doc/faq.html:

View File

@ -2450,129 +2450,135 @@ void edit_draw(const filestruct *fileptr, const char *converted, int
goto step_two; goto step_two;
start_line = start_line->prev; start_line = start_line->prev;
} }
/* No start found, so skip to the next step. */ if (startmatch.rm_so == startmatch.rm_eo) {
if (start_line == NULL) startmatch.rm_eo++;
goto step_two; statusbar(_("Refusing zero-length regex match"));
/* Now start_line is the first line before fileptr } else {
* containing a start match. Is there a start on this /* No start found, so skip to the next step. */
* line not followed by an end on this line? */ if (start_line == NULL)
start_col = 0;
while (TRUE) {
start_col += startmatch.rm_so;
startmatch.rm_eo -= startmatch.rm_so;
if (regexec(tmpcolor->end, start_line->data +
start_col + startmatch.rm_eo, 0, NULL,
(start_col + startmatch.rm_eo == 0) ? 0 :
REG_NOTBOL) == REG_NOMATCH)
/* No end found after this start. */
break;
start_col++;
if (regexec(tmpcolor->start, start_line->data +
start_col, 1, &startmatch, REG_NOTBOL) ==
REG_NOMATCH)
/* No later start on this line. */
goto step_two; goto step_two;
} /* Now start_line is the first line before fileptr
/* Indeed, there is a start not followed on this line by * containing a start match. Is there a start on
* an end. */ * this line not followed by an end on this line? */
start_col = 0;
while (TRUE) {
start_col += startmatch.rm_so;
startmatch.rm_eo -= startmatch.rm_so;
if (regexec(tmpcolor->end, start_line->data +
start_col + startmatch.rm_eo, 0, NULL,
(start_col + startmatch.rm_eo == 0) ?
0 : REG_NOTBOL) == REG_NOMATCH)
/* No end found after this start. */
break;
start_col++;
if (regexec(tmpcolor->start, start_line->data +
start_col, 1, &startmatch,
REG_NOTBOL) == REG_NOMATCH)
/* No later start on this line. */
goto step_two;
}
/* Indeed, there is a start not followed on this
* line by an end. */
/* We have already checked that there is no end before /* We have already checked that there is no end
* fileptr and after the start. Is there an end after * before fileptr and after the start. Is there an
* the start at all? We don't paint unterminated * end after the start at all? We don't paint
* starts. */ * unterminated starts. */
end_line = fileptr; end_line = fileptr;
while (end_line != NULL && regexec(tmpcolor->end, while (end_line != NULL && regexec(tmpcolor->end,
end_line->data, 1, &endmatch, 0) == REG_NOMATCH) end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
end_line = end_line->next; end_line = end_line->next;
/* No end found, or it is too early. */ /* No end found, or it is too early. */
if (end_line == NULL || (end_line == fileptr && if (end_line == NULL || (end_line == fileptr &&
endmatch.rm_eo <= startpos)) endmatch.rm_eo <= startpos))
goto step_two; goto step_two;
/* Now paint the start of fileptr. */ /* Now paint the start of fileptr. */
if (end_line != fileptr) if (end_line != fileptr)
/* If the start of fileptr is on a different line /* If the start of fileptr is on a different
* from the end, paintlen is -1, meaning that * line from the end, paintlen is -1, meaning
* everything on the line gets painted. */ * that everything on the line gets painted. */
paintlen = -1; paintlen = -1;
else else
/* Otherwise, paintlen is the expanded location of /* Otherwise, paintlen is the expanded location
* the end of the match minus the expanded location * of the end of the match minus the expanded
* of the beginning of the page. */ * location of the beginning of the page. */
paintlen = actual_x(converted, paintlen = actual_x(converted,
strnlenpt(fileptr->data, endmatch.rm_eo) - strnlenpt(fileptr->data,
start); endmatch.rm_eo) - start);
mvwaddnstr(edit, line, 0, converted, paintlen); mvwaddnstr(edit, line, 0, converted, paintlen);
step_two: step_two:
/* Second step, we look for starts on this line. */ /* Second step, we look for starts on this line. */
start_col = 0; start_col = 0;
while (start_col < endpos) { while (start_col < endpos) {
if (regexec(tmpcolor->start, fileptr->data + if (regexec(tmpcolor->start, fileptr->data +
start_col, 1, &startmatch, (start_col == 0) ? start_col, 1, &startmatch, (start_col ==
0 : REG_NOTBOL) == REG_NOMATCH || start_col + 0) ? 0 : REG_NOTBOL) == REG_NOMATCH ||
startmatch.rm_so >= endpos) start_col + startmatch.rm_so >= endpos)
/* No more starts on this line. */ /* No more starts on this line. */
break; break;
/* Translate the match to be relative to the /* Translate the match to be relative to the
* beginning of the line. */ * beginning of the line. */
startmatch.rm_so += start_col; startmatch.rm_so += start_col;
startmatch.rm_eo += start_col; startmatch.rm_eo += start_col;
if (startmatch.rm_so <= startpos) x_start = (startmatch.rm_so <= startpos) ? 0 :
x_start = 0; strnlenpt(fileptr->data,
else
x_start = strnlenpt(fileptr->data,
startmatch.rm_so) - start; startmatch.rm_so) - start;
index = actual_x(converted, x_start); index = actual_x(converted, x_start);
if (regexec(tmpcolor->end, fileptr->data + if (regexec(tmpcolor->end, fileptr->data +
startmatch.rm_eo, 1, &endmatch, startmatch.rm_eo, 1, &endmatch,
(startmatch.rm_eo == 0) ? 0 : REG_NOTBOL) == (startmatch.rm_eo == 0) ? 0 :
0) { REG_NOTBOL) == 0) {
/* Translate the end match to be relative to the /* Translate the end match to be relative to
* beginning of the line. */ * the beginning of the line. */
endmatch.rm_so += startmatch.rm_eo; endmatch.rm_so += startmatch.rm_eo;
endmatch.rm_eo += startmatch.rm_eo; endmatch.rm_eo += startmatch.rm_eo;
/* There is an end on this line. But does it /* There is an end on this line. But does
* appear on this page, and is the match more * it appear on this page, and is the match
* than zero characters long? */ * more than zero characters long? */
if (endmatch.rm_eo > startpos && if (endmatch.rm_eo > startpos &&
endmatch.rm_eo > startmatch.rm_so) { endmatch.rm_eo > startmatch.rm_so) {
paintlen = actual_x(converted + index, paintlen = actual_x(converted + index,
strnlenpt(fileptr->data, strnlenpt(fileptr->data,
endmatch.rm_eo) - start - x_start); endmatch.rm_eo) - start -
x_start);
assert(0 <= x_start && x_start < COLS); assert(0 <= x_start && x_start < COLS);
mvwaddnstr(edit, line, x_start, converted + mvwaddnstr(edit, line, x_start,
index, paintlen); converted + index, paintlen);
} }
} else { } else {
/* There is no end on this line. But we haven't /* There is no end on this line. But we
* yet looked for one on later lines. */ * haven't yet looked for one on later
end_line = fileptr->next; * lines. */
end_line = fileptr->next;
while (end_line != NULL && while (end_line != NULL &&
regexec(tmpcolor->end, end_line->data, regexec(tmpcolor->end, end_line->data,
0, NULL, 0) == REG_NOMATCH) 0, NULL, 0) == REG_NOMATCH)
end_line = end_line->next; end_line = end_line->next;
if (end_line != NULL) { if (end_line != NULL) {
assert(0 <= x_start && x_start < COLS); assert(0 <= x_start && x_start < COLS);
mvwaddnstr(edit, line, x_start, converted + mvwaddnstr(edit, line, x_start,
index, -1); converted + index, -1);
/* We painted to the end of the line, so /* We painted to the end of the line, so
* don't bother checking any more starts. */ * don't bother checking any more
break; * starts. */
break;
}
} }
start_col = startmatch.rm_so + 1;
} }
start_col = startmatch.rm_so + 1;
} }
} }