#include <ctype.h>
#include <stdlib.h>
+#include <errno.h>
#define IMAP_CMD_BUFSIZE 512
dprint (2, (debugfile, "Handling EXISTS\n"));
/* new mail arrived */
- count = atoi (pn);
+ mutt_atoui (pn, &count);
if ( !(idata->reopen & IMAP_EXPUNGE_PENDING) &&
count < idata->max_msn)
dprint (2, (debugfile, "Handling EXPUNGE\n"));
- exp_msn = atoi (s);
- if (exp_msn < 1 || exp_msn > idata->max_msn)
+ if (mutt_atoui (s, &exp_msn) < 0 ||
+ exp_msn < 1 || exp_msn > idata->max_msn)
return;
h = idata->msn_index[exp_msn - 1];
dprint (3, (debugfile, "Handling FETCH\n"));
- msn = atoi (s);
- if (msn < 1 || msn > idata->max_msn)
+ if (mutt_atoui (s, &msn) < 0 ||
+ msn < 1 || msn > idata->max_msn)
{
dprint (3, (debugfile, "FETCH response ignored for this message\n"));
return;
return;
}
- dprint (2, (debugfile, "Message UID %d updated\n", HEADER_DATA(h)->uid));
+ dprint (2, (debugfile, "Message UID %u updated\n", HEADER_DATA(h)->uid));
/* skip FETCH */
s = imap_next_word (s);
s = imap_next_word (s);
{
s += 3;
SKIPWS (s);
- uid = (unsigned int) atoi (s);
+ if (mutt_atoui (s, &uid) < 0)
+ {
+ dprint (2, (debugfile, "Illegal UID. Skipping update.\n"));
+ return;
+ }
if (uid != HEADER_DATA(h)->uid)
{
dprint (2, (debugfile, "FETCH UID vs MSN mismatch. Skipping update.\n"));
while ((s = imap_next_word ((char*)s)) && *s != '\0')
{
- uid = (unsigned int)atoi (s);
+ if (mutt_atoui (s, &uid) < 0)
+ continue;
h = (HEADER *)int_hash_find (idata->uid_hash, uid);
if (h)
h->matched = 1;
char* value;
BUFFY* inc;
IMAP_MBOX mx;
- int count;
+ unsigned int count;
IMAP_STATUS *status;
unsigned int olduv, oldun;
long litlen;
while (*s && *s != ')')
{
value = imap_next_word (s);
- count = strtol (value, &value, 10);
+
+ errno = 0;
+ count = strtoul (value, &value, 10);
+ if (errno == ERANGE && count == ULONG_MAX)
+ {
+ dprint (1, (debugfile, "Error parsing STATUS number\n"));
+ return;
+ }
if (!ascii_strncmp ("MESSAGES", s, 8))
{
if (*s && *s != ')')
s = imap_next_word (s);
}
- dprint (3, (debugfile, "%s (UIDVALIDITY: %d, UIDNEXT: %d) %d messages, %d recent, %d unseen\n",
+ dprint (3, (debugfile, "%s (UIDVALIDITY: %u, UIDNEXT: %u) %d messages, %d recent, %d unseen\n",
status->name, status->uidvalidity, status->uidnext,
status->messages, status->recent, status->unseen));
if (value && !imap_mxcmp (mailbox, value))
{
- dprint (3, (debugfile, "Found %s in buffy list (OV: %d ON: %d U: %d)\n",
+ dprint (3, (debugfile, "Found %s in buffy list (OV: %u ON: %u U: %d)\n",
mailbox, olduv, oldun, status->unseen));
if (option(OPTMAILCHECKRECENT))
if (h->index == INT_MAX)
{
- dprint (2, (debugfile, "Expunging message UID %d.\n", HEADER_DATA (h)->uid));
+ dprint (2, (debugfile, "Expunging message UID %u.\n", HEADER_DATA (h)->uid));
h->active = 0;
idata->ctx->size -= h->content->length;
dprint (3, (debugfile, "Getting mailbox UIDVALIDITY\n"));
pc += 3;
pc = imap_next_word (pc);
- idata->uid_validity = strtol (pc, NULL, 10);
+ if (mutt_atoui (pc, &idata->uid_validity) < 0)
+ goto fail;
status->uidvalidity = idata->uid_validity;
}
else if (ascii_strncasecmp ("OK [UIDNEXT", pc, 11) == 0)
dprint (3, (debugfile, "Getting mailbox UIDNEXT\n"));
pc += 3;
pc = imap_next_word (pc);
- idata->uidnext = strtol (pc, NULL, 10);
+ if (mutt_atoui (pc, &idata->uidnext) < 0)
+ goto fail;
status->uidnext = idata->uidnext;
}
else
}
status->uidvalidity = *uidvalidity;
status->uidnext = uidnext ? *uidnext: 0;
- dprint (3, (debugfile, "mboxcache: hcache uidvalidity %d, uidnext %d\n",
+ dprint (3, (debugfile, "mboxcache: hcache uidvalidity %u, uidnext %u\n",
status->uidvalidity, status->uidnext));
}
mutt_hcache_free ((void **)&uidvalidity);
char *pc;
long bytes;
progress_t progressbar;
- int uid;
+ unsigned int uid;
int cacheno;
IMAP_CACHE *cache;
int read;
if (ascii_strncasecmp ("UID", pc, 3) == 0)
{
pc = imap_next_word (pc);
- uid = atoi (pc);
+ if (mutt_atoui (pc, &uid) < 0)
+ goto bail;
if (uid != HEADER_DATA(h)->uid)
mutt_error (_("The message index is incorrect. Try reopening the mailbox."));
}
/* skip to message number */
buf = imap_next_word (buf);
- h->data->msn = atoi (buf);
+ if (mutt_atoui (buf, &h->data->msn) < 0)
+ return rc;
/* find FETCH tag */
buf = imap_next_word (buf);
{
s += 3;
SKIPWS (s);
- h->data->uid = (unsigned int) atoi (s);
+ if (mutt_atoui (s, &h->data->uid) < 0)
+ return -1;
s = imap_next_word (s);
}
while (isdigit ((unsigned char) *s))
*ptmp++ = *s++;
*ptmp = 0;
- h->content_length = atoi (tmp);
+ if (mutt_atol (tmp, &h->content_length) < 0)
+ return -1;
}
else if (!ascii_strncasecmp ("BODY", s, 4) ||
!ascii_strncasecmp ("RFC822.HEADER", s, 13))
return -1;
return 0;
}
+
+/* NOTE: this function's return value breaks with the above three functions.
+ * The imap code lexes uint values out of a stream of characters without
+ * tokenization. The above functions return -1 if there is input beyond
+ * the number.
+ *
+ * returns: 1 - successful conversion, with trailing characters
+ * 0 - successful conversion
+ * -1 - invalid input
+ * -2 - input out of range
+ */
+int mutt_atoui (const char *str, unsigned int *dst)
+{
+ int rc;
+ unsigned long res;
+ unsigned int tmp;
+ unsigned int *t = dst ? dst : &tmp;
+
+ *t = 0;
+
+ if ((rc = mutt_atoul (str, &res)) < 0)
+ return rc;
+ if ((unsigned int) res != res)
+ return -2;
+
+ *t = (unsigned int) res;
+ return rc;
+}
+
+/* NOTE: this function's return value is different from mutt_atol.
+ *
+ * returns: 1 - successful conversion, with trailing characters
+ * 0 - successful conversion
+ * -1 - invalid input
+ */
+int mutt_atoul (const char *str, unsigned long *dst)
+{
+ unsigned long r;
+ unsigned long *res = dst ? dst : &r;
+ char *e = NULL;
+
+ /* no input: 0 */
+ if (!str || !*str)
+ {
+ *res = 0;
+ return 0;
+ }
+
+ errno = 0;
+ *res = strtoul (str, &e, 10);
+ if (*res == ULONG_MAX && errno == ERANGE)
+ return -1;
+ if (e && *e != '\0')
+ return 1;
+ return 0;
+}
int mutt_atos (const char *, short *);
int mutt_atoi (const char *, int *);
int mutt_atol (const char *, long *);
+int mutt_atoui (const char *, unsigned int *);
+int mutt_atoul (const char *, unsigned long *);
const char *mutt_stristr (const char *, const char *);
const char *mutt_basename (const char *);