]> granicus.if.org Git - mutt/commitdiff
Prevent trying to match a failing color body regex repeatedly.
authorKevin McCarthy <kevin@8t8.us>
Mon, 26 Nov 2018 03:48:49 +0000 (19:48 -0800)
committerKevin McCarthy <kevin@8t8.us>
Mon, 26 Nov 2018 03:48:49 +0000 (19:48 -0800)
Emails with really long lines (e.g. spam), can suffer performance if a
complicated regex is matched to no effect over and over.  If the regex
failed at the beginning, it won't match at the end of another's regex
match range, so turn it off.

mutt_curses.h
pager.c

index d12b57905cfe12dfb260426d61144b0612773394..bd563f7b7aa1d9b75c7597af7c62923a46224e17 100644 (file)
@@ -153,6 +153,10 @@ typedef struct color_line
   short bg;
   int pair;
   struct color_line *next;
+
+  unsigned int stop_matching : 1; /* used by the pager for body patterns,
+                                     to prevent the color from being retried
+                                     once it fails. */
 } COLOR_LINE;
 
 #define MUTT_PROGRESS_SIZE      (1<<0)  /* traffic-based progress */
diff --git a/pager.c b/pager.c
index 930c1916ebab4b0bea20d7550b9a0f8aded82c42..5fb8629dbcb138defa5d1aca6ac5793b31270414 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -751,7 +751,7 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last,
                struct q_class_t **QuoteList, int *q_level, int *force_redraw,
                int q_classify)
 {
-  COLOR_LINE *color_line;
+  COLOR_LINE *color_line, *color_list;
   regmatch_t pmatch[1];
   int found, offset, null_rx, i;
 
@@ -872,6 +872,16 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last,
     i = 0;
     offset = 0;
     lineInfo[n].chunks = 0;
+    if (lineInfo[n].type == MT_COLOR_HDEFAULT)
+      color_list = ColorHdrList;
+    else
+      color_list = ColorBodyList;
+    color_line = color_list;
+    while (color_line)
+    {
+      color_line->stop_matching = 0;
+      color_line = color_line->next;
+    }
     do
     {
       if (!buf[offset])
@@ -879,13 +889,11 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last,
 
       found = 0;
       null_rx = 0;
-      if (lineInfo[n].type == MT_COLOR_HDEFAULT)
-        color_line = ColorHdrList;
-      else
-        color_line = ColorBodyList;
+      color_line = color_list;
       while (color_line)
       {
-       if (regexec (&color_line->rx, buf + offset, 1, pmatch,
+       if (!color_line->stop_matching &&
+            regexec (&color_line->rx, buf + offset, 1, pmatch,
                     (offset ? REG_NOTBOL : 0)) == 0)
        {
          if (pmatch[0].rm_eo != pmatch[0].rm_so)
@@ -921,6 +929,11 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last,
          else
            null_rx = 1; /* empty regexp; don't add it, but keep looking */
        }
+        /* Once a regexp fails to match, don't try matching it again.
+         * On very long lines this can cause a performance issue if there
+         * are other regexps that have many matches. */
+        else
+          color_line->stop_matching = 1;
        color_line = color_line->next;
       }