]> granicus.if.org Git - neomutt/commitdiff
Do not cache a compiled regex to avoid leaks
authorPietro Cerutti <gahr@gahr.ch>
Mon, 13 May 2019 11:42:37 +0000 (11:42 +0000)
committerRichard Russon <rich@flatcap.org>
Mon, 13 May 2019 12:00:04 +0000 (13:00 +0100)
glibc's implementation of the regex engine is a DFA which creates nodes
on the fly under the regex_t object. This will cause leakes if we keep
the compiled regular expression around, as it was the case before.

See also https://sourceware.org/bugzilla/show_bug.cgi?id=12567

email/rfc2047.c

index 5857cb355cdf75cd28f53ae4881fcc949aee2125..94b4e8da90e31f4af442ef7d5c08b1393f14a348 100644 (file)
@@ -139,13 +139,9 @@ static size_t q_encoder(char *str, const char *buf, size_t buflen, const char *t
 static char *parse_encoded_word(char *str, enum ContentEncoding *enc, char **charset,
                                 size_t *charsetlen, char **text, size_t *textlen)
 {
-  static struct Regex *re = NULL;
   regmatch_t match[4];
   size_t nmatch = 4;
-
-  if (!re)
-  {
-    re = mutt_regex_compile("=\\?"
+  struct Regex *re = mutt_regex_compile("=\\?"
                             "([^][()<>@,;:\\\"/?. =]+)" /* charset */
                             "\\?"
                             "([qQbB])" /* encoding */
@@ -154,25 +150,28 @@ static char *parse_encoded_word(char *str, enum ContentEncoding *enc, char **cha
                                          as some mailers do that, see #1189. */
                             "\\?=",
                             REG_EXTENDED);
-    assert(re && "Something is wrong with your RE engine.");
-  }
+  assert(re && "Something is wrong with your RE engine.");
 
+  char *res = NULL;
   int rc = regexec(re->regex, str, nmatch, match, 0);
-  if (rc != 0)
-    return NULL;
-
-  /* Charset */
-  *charset = str + match[1].rm_so;
-  *charsetlen = match[1].rm_eo - match[1].rm_so;
-
-  /* Encoding: either Q or B */
-  *enc = ((str[match[2].rm_so] == 'Q') || (str[match[2].rm_so] == 'q')) ?
-             ENC_QUOTED_PRINTABLE :
-             ENC_BASE64;
+  if (rc == 0)
+  {
+    /* Charset */
+    *charset = str + match[1].rm_so;
+    *charsetlen = match[1].rm_eo - match[1].rm_so;
+
+    /* Encoding: either Q or B */
+    *enc = ((str[match[2].rm_so] == 'Q') || (str[match[2].rm_so] == 'q')) ?
+               ENC_QUOTED_PRINTABLE :
+               ENC_BASE64;
+
+    *text = str + match[3].rm_so;
+    *textlen = match[3].rm_eo - match[3].rm_so;
+    res = str + match[0].rm_so;
+  }
 
-  *text = str + match[3].rm_so;
-  *textlen = match[3].rm_eo - match[3].rm_so;
-  return str + match[0].rm_so;
+  mutt_regex_free(&re);
+  return res;
 }
 
 /**