]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
If we detect cached header is corrupted while unfolding it, mark the cache corrupted.
authorTimo Sirainen <tss@iki.fi>
Thu, 19 Feb 2009 18:08:50 +0000 (13:08 -0500)
committerTimo Sirainen <tss@iki.fi>
Thu, 19 Feb 2009 18:08:50 +0000 (13:08 -0500)
--HG--
branch : HEAD

src/lib-storage/index/index-mail-headers.c

index d362df271c820817f9a5305adb711fd9bed9e88b..cbf39a6c5aa41b734711775bf3461cac03f9545b 100644 (file)
@@ -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,