Commit message: Ensure litlen isn't larger than our mailbox
CVE: CVE-2018-14351
CWE: CWE-20
Vulnerability description: An issue was discovered in Mutt before 1.10.1 and NeoMutt before 2018-07-16. imap/command.c mishandles a long IMAP status mailbox literal count size.

Project: neomutt
File: command.c

static int cmd_handle_untagged(struct ImapData *idata)
{
  unsigned int count = 0;
  char *s = imap_next_word(idata->buf);
  char *pn = imap_next_word(s);

  if ((idata->state >= IMAP_SELECTED) && isdigit((unsigned char) *s))
  {
    pn = s;
    s = imap_next_word(s);

    /* EXISTS and EXPUNGE are always related to the SELECTED mailbox for the
     * connection, so update that one.
     */
    if (mutt_str_strncasecmp("EXISTS", s, 6) == 0)
    {
      mutt_debug(2, "Handling EXISTS\n");

      /* new mail arrived */
      if (mutt_str_atoui(pn, &count) < 0)
      {
        mutt_debug(1, "Malformed EXISTS: '%s'\n", pn);
      }

      if (!(idata->reopen & IMAP_EXPUNGE_PENDING) && count < idata->max_msn)
      {
        /* Notes 6.0.3 has a tendency to report fewer messages exist than
         * it should. */
        mutt_debug(1, "Message count is out of sync\n");
        return 0;
      }
      /* at least the InterChange server sends EXISTS messages freely,
       * even when there is no new mail */
      else if (count == idata->max_msn)
        mutt_debug(3, "superfluous EXISTS message.\n");
      else
      {
        if (!(idata->reopen & IMAP_EXPUNGE_PENDING))
        {
          mutt_debug(2, "New mail in %s - %d messages total.\n", idata->mailbox, count);
          idata->reopen |= IMAP_NEWMAIL_PENDING;
        }
        idata->new_mail_count = count;
      }
    }
    /* pn vs. s: need initial seqno */
    else if (mutt_str_strncasecmp("EXPUNGE", s, 7) == 0)
      cmd_parse_expunge(idata, pn);
    else if (mutt_str_strncasecmp("FETCH", s, 5) == 0)
      cmd_parse_fetch(idata, pn);
  }
  else if (mutt_str_strncasecmp("CAPABILITY", s, 10) == 0)
    cmd_parse_capability(idata, s);
  else if (mutt_str_strncasecmp("OK [CAPABILITY", s, 14) == 0)
    cmd_parse_capability(idata, pn);
  else if (mutt_str_strncasecmp("OK [CAPABILITY", pn, 14) == 0)
    cmd_parse_capability(idata, imap_next_word(pn));
  else if (mutt_str_strncasecmp("LIST", s, 4) == 0)
    cmd_parse_list(idata, s);
  else if (mutt_str_strncasecmp("LSUB", s, 4) == 0)
    cmd_parse_lsub(idata, s);
  else if (mutt_str_strncasecmp("MYRIGHTS", s, 8) == 0)
    cmd_parse_myrights(idata, s);
  else if (mutt_str_strncasecmp("SEARCH", s, 6) == 0)
    cmd_parse_search(idata, s);
  else if (mutt_str_strncasecmp("STATUS", s, 6) == 0)
    cmd_parse_status(idata, s);
  else if (mutt_str_strncasecmp("ENABLED", s, 7) == 0)
    cmd_parse_enabled(idata, s);
  else if (mutt_str_strncasecmp("BYE", s, 3) == 0)
  {
    mutt_debug(2, "Handling BYE\n");

    /* check if we're logging out */
    if (idata->status == IMAP_BYE)
      return 0;

    /* server shut down our connection */
    s += 3;
    SKIPWS(s);
    mutt_error("%s", s);
    cmd_handle_fatal(idata);

    return -1;
  }
  else if (ImapServernoise && (mutt_str_strncasecmp("NO", s, 2) == 0))
  {
    mutt_debug(2, "Handling untagged NO\n");

    /* Display the warning message from the server */
    mutt_error("%s", s + 2);
  }

  return 0;
}

Project: neomutt
File: command.c

static void cmd_parse_lsub(struct ImapData *idata, char *s)
{
  char buf[STRING];
  char errstr[STRING];
  struct Buffer err, token;
  struct Url url;
  struct ImapList list;

  if (idata->cmddata && idata->cmdtype == IMAP_CT_LIST)
  {
    /* caller will handle response itself */
    cmd_parse_list(idata, s);
    return;
  }

  if (!ImapCheckSubscribed)
    return;

  idata->cmdtype = IMAP_CT_LIST;
  idata->cmddata = &list;
  cmd_parse_list(idata, s);
  idata->cmddata = NULL;
  /* noselect is for a gmail quirk (#3445) */
  if (!list.name || list.noselect)
    return;

  mutt_debug(3, "Subscribing to %s\n", list.name);

  mutt_str_strfcpy(buf, "mailboxes \"", sizeof(buf));
  mutt_account_tourl(&idata->conn->account, &url);
  /* escape \ and " */
  imap_quote_string(errstr, sizeof(errstr), list.name, true);
  url.path = errstr + 1;
  url.path[strlen(url.path) - 1] = '\0';
  if (mutt_str_strcmp(url.user, ImapUser) == 0)
    url.user = NULL;
  url_tostring(&url, buf + 11, sizeof(buf) - 11, 0);
  mutt_str_strcat(buf, sizeof(buf), "\"");
  mutt_buffer_init(&token);
  mutt_buffer_init(&err);
  err.data = errstr;
  err.dsize = sizeof(errstr);
  if (mutt_parse_rc_line(buf, &token, &err))
    mutt_debug(1, "Error adding subscribed mailbox: %s\n", errstr);
  FREE(&token.data);
}