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);

Reply via email to