#include "config.h"
#include <ctype.h>
+#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
mutt_debug(2, "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];
mutt_debug(3, "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)
{
mutt_debug(3, "#1 FETCH response ignored for this message\n");
return;
return;
}
- mutt_debug(2, "Message UID %d updated\n", HEADER_DATA(h)->uid);
+ mutt_debug(2, "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)
+ {
+ mutt_debug(2, "Illegal UID. Skipping update.\n");
+ return;
+ }
if (uid != HEADER_DATA(h)->uid)
{
mutt_debug(2, "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 = (struct Header *) mutt_hash_int_find(idata->uid_hash, uid);
if (h)
h->matched = true;
char *value = NULL;
struct Buffy *inc = NULL;
struct ImapMbox mx;
- int count;
+ unsigned int count;
struct ImapStatus *status = NULL;
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)
+ {
+ mutt_debug(1, "Error parsing STATUS number\n");
+ return;
+ }
if (mutt_str_strncmp("MESSAGES", s, 8) == 0)
{
}
mutt_debug(
3,
- "%s (UIDVALIDITY: %d, UIDNEXT: %d) %d messages, %d recent, %d unseen\n",
+ "%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) == 0))
{
- mutt_debug(3, "Found %s in buffy list (OV: %d ON: %d U: %d)\n", mailbox,
+ mutt_debug(3, "Found %s in buffy list (OV: %u ON: %u U: %d)\n", mailbox,
olduv, oldun, status->unseen);
if (MailCheckRecent)
mutt_debug(2, "Handling EXISTS\n");
/* new mail arrived */
- count = atoi(pn);
+ mutt_atoui(pn, &count);
if (!(idata->reopen & IMAP_EXPUNGE_PENDING) && count < idata->max_msn)
{
if (h->index == INT_MAX)
{
- mutt_debug(2, "Expunging message UID %d.\n", HEADER_DATA(h)->uid);
+ mutt_debug(2, "Expunging message UID %u.\n", HEADER_DATA(h)->uid);
h->active = false;
idata->ctx->size -= h->content->length;
}
status->uidvalidity = *(unsigned int *) uidvalidity;
status->uidnext = uidnext ? *(unsigned int *) uidnext : 0;
- mutt_debug(3, "hcache uidvalidity %d, uidnext %d\n", status->uidvalidity,
+ mutt_debug(3, "hcache uidvalidity %u, uidnext %u\n", status->uidvalidity,
status->uidnext);
}
mutt_hcache_free(hc, &uidvalidity);
mutt_debug(3, "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 (mutt_str_strncasecmp("OK [UIDNEXT", pc, 11) == 0)
mutt_debug(3, "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
{
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_str_atol(tmp, &h->content_length) < 0)
+ return -1;
}
else if ((mutt_str_strncasecmp("BODY", s, 4) == 0) ||
(mutt_str_strncasecmp("RFC822.HEADER", s, 13) == 0))
/* 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);
char *pc = NULL;
long bytes;
struct Progress progressbar;
- int uid;
+ unsigned int uid;
int cacheno;
struct ImapCache *cache = NULL;
bool read;
if (mutt_str_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."));
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_addrlist_to_intl(struct Address *a, char **err);
int mutt_addrlist_to_local(struct Address *a);
+int mutt_atoui(const char *str, unsigned int *dst);
+int mutt_atoul(const char *str, unsigned long *dst);
+
#endif /* _MUTT_PROTOS_H */