diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2005-05-13 09:38:56 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2005-05-13 09:38:56 +0000 |
commit | 9c1f689b6b0a987b67fee97288aaba5654ae96db (patch) | |
tree | 3b9829379432f86a26c06cf59911f6866aaff4f1 | |
parent | 2de526cd873efd03973486e526668d150c1fc153 (diff) | |
download | mailutils-9c1f689b6b0a987b67fee97288aaba5654ae96db.tar.gz mailutils-9c1f689b6b0a987b67fee97288aaba5654ae96db.tar.bz2 |
(imap4d_fetch0): Reduce memory consumption within
the mailbox scanning loop. Break the loop when an invalid msgno is
encountered or the message cannot be retrieved.
(fetch_io): Check for integer overflow (IDEF0956).
(fetch_full,fetch_rfc822_header,fetch_rfc822_text)
(fetch_operation): Propagate return value back to the caller.
-rw-r--r-- | imap4d/fetch.c | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/imap4d/fetch.c b/imap4d/fetch.c index 937173b59..2f8d58b11 100644 --- a/imap4d/fetch.c +++ b/imap4d/fetch.c @@ -136,7 +136,7 @@ int imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen) { struct fetch_command *fcmd = NULL; - int rc = RESP_NO; + int rc = RESP_OK; char *sp = NULL; char *msgset; size_t *set = NULL; @@ -159,25 +159,29 @@ imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen) return RESP_BAD; } - for (i = 0; i < n; i++) + /* Prepare status code. It will be replaced if an error occurs in the + loop below */ + snprintf (resp, resplen, "Completed"); + + for (i = 0; i < n && rc == RESP_OK; i++) { - char item[32]; - char *items = strdup (sp); - char *p = items; - size_t msgno; - int space = 0; + size_t msgno = (isuid) ? uid_to_msgno (set[i]) : set[i]; message_t msg = NULL; - msgno = (isuid) ? uid_to_msgno (set[i]) : set[i]; if (msgno && mailbox_get_message (mbox, msgno, &msg) == 0) { + char item[32]; + char *items = strdup (sp); + char *p = items; + int space = 0; + fcmd = NULL; util_send ("* %d FETCH (", msgno); item[0] = '\0'; /* Server implementations MUST implicitly - include the UID message data item as part of any FETCH response - caused by a UID command, regardless of whether a UID was specified - as a message data item to the FETCH. */ + include the UID message data item as part of any FETCH + response caused by a UID command, regardless of whether + a UID was specified as a message data item to the FETCH. */ if (isuid) { fcmd = &fetch_command_table[F_UID]; @@ -190,7 +194,7 @@ imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen) util_token (item, sizeof (item), &items); /* Do not send the UID again. */ if (isuid && strcasecmp (item, "UID") == 0) - continue; + continue; if (fcmd) space = 1; /* Search in the table. */ @@ -207,12 +211,18 @@ imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen) } } util_send (")\r\n"); + free (p); + } + else + { + snprintf (resp, resplen, + "Bogus message set: message number out of range"); + rc = RESP_BAD; + break; } - free (p); } free (set); - snprintf (resp, resplen, "Completed"); - return RESP_OK; + return rc; } /* ALL: @@ -240,8 +250,7 @@ fetch_full (struct fetch_command *command, char **arg) fetch_all (command, arg); util_send (" "); c_body.msg = command->msg; - fetch_body (&c_body, arg); - return RESP_OK; + return fetch_body (&c_body, arg); } /* FAST: @@ -372,8 +381,7 @@ fetch_rfc822_header (struct fetch_command *command, char **arg ARG_UNUSED) char *p = buffer; strcpy (buffer, ".PEEK[HEADER]"); - fetch_body (command, &p); - return RESP_OK; + return fetch_body (command, &p); } /* RFC822.TEXT: @@ -386,8 +394,7 @@ fetch_rfc822_text (struct fetch_command *command, char **arg ARG_UNUSED) char *p = buffer; strcpy (buffer, "[TEXT]"); - fetch_body (command, &p); - return RESP_OK; + return fetch_body (command, &p); } /* The [RFC-822] size of the message. */ @@ -955,7 +962,8 @@ fetch_operation (message_t msg, char **arg, int silent) unsigned long end = ULONG_MAX; /* No limit. */ char *section; /* Hold the section number string. */ char *partial = strchr (*arg, '<'); - + int rc; + /* Check for section specific offset. */ if (partial) { @@ -1009,13 +1017,15 @@ fetch_operation (message_t msg, char **arg, int silent) else section = calloc (1, 1); + rc = RESP_OK; + /* Choose the right fetch attribute. */ if (*section == '\0' && **arg == ']') { if (!silent) util_send ("[]"); (*arg)++; - fetch_message (msg, start, end); + rc = fetch_message (msg, start, end); } else if (strncasecmp (*arg, "HEADER]", 7) == 0) { @@ -1029,7 +1039,7 @@ fetch_operation (message_t msg, char **arg, int silent) util_send ("[%sHEADER]", section); } (*arg) += 7; - fetch_header (msg, start, end); + rc = fetch_header (msg, start, end); } else if (strncasecmp (*arg, "MIME]", 5) == 0) { @@ -1041,7 +1051,7 @@ fetch_operation (message_t msg, char **arg, int silent) util_send ("[%s", *arg); } (*arg) += 5; - fetch_header (msg, start, end); + rc = fetch_header (msg, start, end); } else if (strncasecmp (*arg, "HEADER.FIELDS.NOT", 17) == 0) { @@ -1052,7 +1062,7 @@ fetch_operation (message_t msg, char **arg, int silent) else util_send ("["); (*arg) += 17; - fetch_header_fields_not (msg, arg, start, end); + rc = fetch_header_fields_not (msg, arg, start, end); } else if (strncasecmp (*arg, "HEADER.FIELDS", 13) == 0) { @@ -1063,7 +1073,7 @@ fetch_operation (message_t msg, char **arg, int silent) else util_send ("["); (*arg) += 13; - fetch_header_fields (msg, arg, start, end); + rc = fetch_header_fields (msg, arg, start, end); } else if (strncasecmp (*arg, "TEXT]", 5) == 0) @@ -1076,19 +1086,22 @@ fetch_operation (message_t msg, char **arg, int silent) util_send ("[TEXT]"); } (*arg) += 5; - fetch_body_content (msg, start, end); + rc = fetch_body_content (msg, start, end); } else if (**arg == ']') { if (!silent) util_send ("[%s]", section); (*arg)++; - fetch_body_content (msg, start, end); + rc = fetch_body_content (msg, start, end); } else - util_send (" \"\"");/*FIXME: ERROR Message!*/ + { + util_send (" \"\"");/*FIXME: ERROR Message!*/ + rc = RESP_BAD; + } free (section); - return RESP_OK; + return rc; } static int @@ -1156,6 +1169,10 @@ fetch_io (stream_t stream, unsigned long start, unsigned long end, else util_send (" \"\""); } + else if (end + 2 < end) /* Check for integer overflow */ + { + return RESP_BAD; + } else { char *buffer, *p; |