From: Timo Sirainen Date: Thu, 19 Feb 2009 18:08:50 +0000 (-0500) Subject: If we detect cached header is corrupted while unfolding it, mark the cache corrupted. X-Git-Tag: 1.2.beta2~82 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=96a464e3e417557153272c964fc8a0e9bb6d6b86;p=thirdparty%2Fdovecot%2Fcore.git If we detect cached header is corrupted while unfolding it, mark the cache corrupted. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c index d362df271c..cbf39a6c5a 100644 --- a/src/lib-storage/index/index-mail-headers.c +++ b/src/lib-storage/index/index-mail-headers.c @@ -650,8 +650,9 @@ index_mail_get_raw_headers(struct index_mail *mail, const char *field, return 0; } -static const char *unfold_header(pool_t pool, const char *str) +static int unfold_header(pool_t pool, const char **_str) { + const char *str = *_str; char *new_str; unsigned int i, j; @@ -660,7 +661,7 @@ static const char *unfold_header(pool_t pool, const char *str) break; } if (str[i] == '\0') - return str; + return 0; /* @UNSAFE */ new_str = p_malloc(pool, i + strlen(str+i) + 1); @@ -671,19 +672,25 @@ static const char *unfold_header(pool_t pool, const char *str) i++; if (str[i] == '\0') break; - i_assert(str[i] == ' ' || str[i] == '\t'); + + if (str[i] != ' ' && str[i] != '\t') { + /* corrupted */ + return -1; + } } else { new_str[j++] = str[i]; } } new_str[j] = '\0'; - return new_str; + *_str = new_str; + return 0; } -static const char *const * -index_mail_headers_decode(struct index_mail *mail, const char *const *list, +static int +index_mail_headers_decode(struct index_mail *mail, const char *const **_list, unsigned int max_count) { + const char *const *list = *_list; const char **decoded_list, *input; unsigned int i, count; string_t *str; @@ -700,28 +707,39 @@ index_mail_headers_decode(struct index_mail *mail, const char *const *list, if (message_header_decode_utf8((const unsigned char *)input, strlen(list[i]), str, FALSE)) input = str_c(str); - input = unfold_header(mail->data_pool, input); + if (unfold_header(mail->data_pool, &input) < 0) + return -1; if (input == str->data) input = p_strdup(mail->data_pool, input); decoded_list[i] = input; } - return decoded_list; + *_list = decoded_list; + return 0; } int index_mail_get_headers(struct mail *_mail, const char *field, bool decode_to_utf8, const char *const **value_r) { struct index_mail *mail = (struct index_mail *)_mail; + int ret, i; - if (index_mail_get_raw_headers(mail, field, value_r) < 0) - return -1; - if (!decode_to_utf8 || **value_r == NULL) - return 0; + for (i = 0; i < 2; i++) { + if (index_mail_get_raw_headers(mail, field, value_r) < 0) + return -1; + if (!decode_to_utf8 || **value_r == NULL) + return 0; - T_BEGIN { - *value_r = index_mail_headers_decode(mail, *value_r, -1U); - } T_END; - return 0; + T_BEGIN { + ret = index_mail_headers_decode(mail, value_r, -1U); + } T_END; + + if (ret < 0) { + mail_cache_set_corrupted(mail->ibox->cache, + "Broken header %s for mail UID %u", + field, _mail->uid); + } + } + return ret; } int index_mail_get_first_header(struct mail *_mail, const char *field, @@ -729,16 +747,28 @@ int index_mail_get_first_header(struct mail *_mail, const char *field, { struct index_mail *mail = (struct index_mail *)_mail; const char *const *list; + int ret, i; + + for (i = 0; i < 2; i++) { + if (index_mail_get_raw_headers(mail, field, &list) < 0) + return -1; + if (!decode_to_utf8 || list[0] == NULL) { + ret = 0; + break; + } - if (index_mail_get_raw_headers(mail, field, &list) < 0) - return -1; - if (decode_to_utf8 && list[0] != NULL) { T_BEGIN { - list = index_mail_headers_decode(mail, list, 1); + ret = index_mail_headers_decode(mail, &list, 1); } T_END; + + if (ret < 0) { + mail_cache_set_corrupted(mail->ibox->cache, + "Broken header %s for mail UID %u", + field, _mail->uid); + } } *value_r = list[0]; - return list[0] != NULL ? 1 : 0; + return ret < 0 ? -1 : (list[0] != NULL ? 1 : 0); } static void header_cache_callback(struct message_header_line *hdr,