Bug 1168463 (CVE-2014-9116) - CVE-2014-9116 mutt: incorrect use of mutt_substrdup() in write_one_header()
Summary: CVE-2014-9116 mutt: incorrect use of mutt_substrdup() in write_one_header()
Alias: CVE-2014-9116
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
Depends On: 1168464
Blocks: 1168468
TreeView+ depends on / blocked
Reported: 2014-11-27 04:05 UTC by Murray McAllister
Modified: 2021-02-17 05:57 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Last Closed: 2015-01-22 13:30:52 UTC

Attachments (Terms of Use)

Description Murray McAllister 2014-11-27 04:05:25 UTC
A heap-based buffer overflow flaw was reported in the mutt_substrdup() function in Mutt. Opening a specially-crafted mail message could cause mutt to crash or, potentially, execute arbitrary code.

CVE request:


In testing on Fedora, "set weed=no" had to be set in the user's .muttrc before the issue presented.

Comment 1 Murray McAllister 2014-11-27 04:05:58 UTC
Created mutt tracking bugs for this issue:

Affects: fedora-all [bug 1168464]

Comment 2 Murray McAllister 2014-11-27 04:16:34 UTC
MITRE assigned CVE-2014-9116 to this issue:


Comment 4 Tomas Hoger 2014-11-27 16:05:46 UTC
(In reply to Murray McAllister from comment #0)
> A heap-based buffer overflow flaw was reported in the mutt_substrdup()
> function in Mutt.

I would not call it a flaw in mutt_substrdup(), but rather in a caller that passes end < begin to mutt_substrdup().  In this case, it's write_one_header().  It seems this code had several problems in the past.

The version of mutt as shipped with Red Hat Enterprise Linux 6 crashes on the mailbox from the original Debian bug report:


However, the cause is different from the cause of crash in more recent mutt versions.  The mutt version in Red Hat Enterprise Linux 6 did not properly check if mail header contains ':' separator, which could cause a NULL pointer dereference (actually, 0x2 pointer is passed to mutt_substrdup() as begin).  This makes mutt_substrdup() write (memcpy) near NULL, causing mutt to crash.

The code is:

   1787     t = strchr (start, ':');
   1788     if (t > end)
   1789     {
   1790       dprint (1, (debugfile, "mwoh: warning: header not in "
   1791 		  "'key: value' format!\n"));
   1792       return 0;
   1793     }
   1800     {
   1801       tagbuf = mutt_substrdup (start, t);
   1802       valbuf = mutt_substrdup (t + 2, end);
   1803     }

Upstream bug and commit that added t != NULL check:


At some point (but before the above t != NULL check was added), the code was changed to not use static t+2 to point to the header value, but skip zero or more white spaces after ':'.  Upstream bug and commit:


The version of mutt as shipped in Red Hat Enterprise Linux 7 has the both above changes, so the code looks as:

   1801     t = strchr (start, ':');
   1802     if (t == NULL || t > end)
   1803     {
   1804       dprint (1, (debugfile, "mwoh: warning: header not in "
   1805 		  "'key: value' format!\n"));
   1806       return 0;
   1807     }
   1814     {
   1815       tagbuf = mutt_substrdup (start, t);
   1816       ++t; /* skip over the colon separating the header field name and value */
   1817       SKIPWS(t); /* skip over any leading whitespace */
   1818       valbuf = mutt_substrdup (t, end);
   1819     }

and SKIPWS is:

     83 # define SKIPWS(c) while (*(c) && isspace ((unsigned char) *(c))) c++;

As this skips newlines, it can lead to mutt_substrdup() called with end < begin.  The problem was already reported upstream and fixed by changing the code to only skip space and tab, but not newlines:


Apparently, the fix was regressed when skip_email_wsp() was added, which made write_one_header() skip newlines again:


The impact of this problem is limited to crash.  This is what mutt_substrdup() does:

    814   size_t len;
    815   char *p;
    817   if (end)
    818     len = end - begin;
    819   else
    820     len = strlen (begin);
    822   p = safe_malloc (len + 1);
    823   memcpy (p, begin, len);

The mailbox file form the Debian bug causes mutt_substrdup() to be called with begin = end + 1, leading to len being SIZE_MAX.  safe_malloc() is called with size 0, which makes it return NULL.  The memcpy() called next attempts to write to memory starting at NULL, which leads to crash.

It is possible to adjust the mailbox to use begin = end + 2 (or more).  That would lead to safe_malloc() called with size that is near SIZE_MAX.  Such allocation does not succeed and causes mutt to abort with "Out of memory!" error.  If changed to use begin = end + n, where n is large enough to not trigger memory allocation failure, there will be no buffer over write, but likely a buffer over read, which is likely to trigger mutt crash.  There may be limits elsewhere in the code making it impossible to make n large enough.

Comment 6 Tomas Hoger 2014-11-28 07:17:55 UTC
Created upstream ticket:


Comment 7 Richard Z. 2014-11-29 11:18:21 UTC
for me it crashes even with "set weed=yes"

Don't think that a segfault is low priority.

Comment 8 Richard Z. 2014-11-29 11:24:29 UTC
noticed that with my settings the crash happens only when looking at the headers with "h". So weed=yes will help only as long as nobody looks at the header at best.

Comment 10 Tomas Hoger 2015-01-07 07:34:04 UTC
Fixed upstream now via:


The fix reverts the change applied via f251d523ca5a (see comment 4 above).

Note You need to log in before you can comment on or make changes to this bug.