When the match for a character is not in the visible part of the
window, mg shows a copy of that line in the echo area. To do so, it
copies the line to a local buffer, so that tabs and control characters
can be rendered properly, but doesn't check for overflow.
NLINE (the size of `buf') is 256, so if the matching parentesis is on
a line longer than 256 characters that's not visible on the screen, we
start writing out-of-bounds and likely crashing.
I've reproduced the crash by editing (a copy of) /bsd which has very
long lines and verified that diff below fixes it. The kernel is nice
for this because it contains a lot of bytes that mg interprets as
controls and so stresses the rendering of control characters.
ok?
Index: match.c
===================================================================
RCS file: /home/cvs/src/usr.bin/mg/match.c,v
retrieving revision 1.23
diff -u -p -r1.23 match.c
--- match.c 17 Apr 2023 09:49:04 -0000 1.23
+++ match.c 17 Apr 2023 13:59:57 -0000
@@ -168,17 +168,23 @@ displaymatch(struct line *clp, int cbo)
/* match is not in this window, so display line in echo area */
bufo = 0;
for (cp = 0; cp < llength(clp); cp++) {
+ if (bufo >= sizeof(buf) - 1)
+ break;
+
c = lgetc(clp, cp);
- if (c != '\t')
+ if (c != '\t') {
if (ISCTRL(c)) {
+ if (bufo + 2 >= sizeof(buf) - 1)
+ break;
buf[bufo++] = '^';
buf[bufo++] = CCHR(c);
} else
buf[bufo++] = c;
- else
+ } else {
do {
buf[bufo++] = ' ';
- } while (bufo & 7);
+ } while ((bufo & 7) && bufo < sizeof(buf) - 1);
+ }
}
buf[bufo++] = '\0';
ewprintf("Matches %s", buf);