]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: message_header_hash_more() now allows input in any slices.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 22 Sep 2016 11:23:00 +0000 (14:23 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 22 Sep 2016 11:45:24 +0000 (14:45 +0300)
There wasn't necessarily any guarantees that the input would be sliced in
such a way that the repeating '?' would be dropped the same way every time.

src/doveadm/dsync/dsync-mail.c
src/lib-mail/message-header-hash.c
src/lib-mail/message-header-hash.h
src/lib-mail/test-message-header-hash.c
src/plugins/pop3-migration/pop3-migration-plugin.c

index 7e93684c05dae4d49d0474c252a7dbda5139d183..9d52d99df73ed8f7852e1cd3aeba9806446c65d6 100644 (file)
@@ -30,6 +30,7 @@ int dsync_mail_get_hdr_hash(struct mail *mail, unsigned int version,
 {
        struct istream *hdr_input, *input;
        struct mailbox_header_lookup_ctx *hdr_ctx;
+       struct message_header_hash_context hash_ctx;
        struct md5_context md5_ctx;
        unsigned char md5_result[MD5_RESULTLEN];
        const unsigned char *data;
@@ -45,13 +46,14 @@ int dsync_mail_get_hdr_hash(struct mail *mail, unsigned int version,
        input = i_stream_create_lf(hdr_input);
 
        md5_init(&md5_ctx);
+       memset(&hash_ctx, 0, sizeof(hash_ctx));
        while (!i_stream_is_eof(input)) {
                if (i_stream_read_data(input, &data, &size, 0) == -1)
                        break;
                if (size == 0)
                        break;
-               message_header_hash_more(&hash_method_md5, &md5_ctx, version,
-                                        data, size);
+               message_header_hash_more(&hash_ctx, &hash_method_md5, &md5_ctx,
+                                        version, data, size);
                i_stream_skip(input, size);
        }
        if (input->stream_errno != 0)
index c1f6d2142637020a6dc59f1cf94a145701c53c8e..62db3fa388c42acbe2df93466c4f512674e9e823 100644 (file)
@@ -4,7 +4,8 @@
 #include "hash-method.h"
 #include "message-header-hash.h"
 
-void message_header_hash_more(const struct hash_method *method, void *context,
+void message_header_hash_more(struct message_header_hash_context *ctx,
+                             const struct hash_method *method, void *context,
                              unsigned int version,
                              const unsigned char *data, size_t size)
 {
@@ -32,12 +33,13 @@ void message_header_hash_more(const struct hash_method *method, void *context,
                if ((data[i] < 0x20 || data[i] >= 0x7f || data[i] == '?') &&
                    (data[i] != '\t' && data[i] != '\n')) {
                        /* remove repeated '?' */
-                       if (start < i || i == 0) {
+                       if (start < i || (i == 0 && !ctx->prev_was_questionmark)) {
                                method->loop(context, data + start, i-start);
                                method->loop(context, "?", 1);
                        }
                        start = i+1;
                }
        }
+       ctx->prev_was_questionmark = start == i;
        method->loop(context, data + start, i-start);
 }
index be6d4499723f7bb777821ac90ed11375aa578b11..cfedd83fdadee95710faaa507ce47381276423da 100644 (file)
@@ -3,7 +3,13 @@
 
 struct hash_method;
 
-void message_header_hash_more(const struct hash_method *method, void *context,
+struct message_header_hash_context {
+       bool prev_was_questionmark;
+};
+
+/* Initialize ctx with zeros. */
+void message_header_hash_more(struct message_header_hash_context *ctx,
+                             const struct hash_method *method, void *context,
                              unsigned int version,
                              const unsigned char *data, size_t size);
 
index 5a32328ccb8e5e648696aa1316adf400aa3a39c7..39fbfe99bdbaff3b739904eac50dfcbafaac02a5 100644 (file)
@@ -14,12 +14,14 @@ static const unsigned char test_output[] =
 
 static void test_dsync_mail_hash_more(void)
 {
+       struct message_header_hash_context ctx;
        struct md5_context md5_ctx;
        unsigned char md5_input[MD5_RESULTLEN], md5_output[MD5_RESULTLEN];
 
        test_begin("dsync_mail_hash_more v2");
        md5_init(&md5_ctx);
-       message_header_hash_more(&hash_method_md5, &md5_ctx, 2,
+       memset(&ctx, 0, sizeof(ctx));
+       message_header_hash_more(&ctx, &hash_method_md5, &md5_ctx, 2,
                                 test_input, sizeof(test_input)-1);
        md5_final(&md5_ctx, md5_input);
 
@@ -28,6 +30,17 @@ static void test_dsync_mail_hash_more(void)
        md5_final(&md5_ctx, md5_output);
 
        test_assert(memcmp(md5_input, md5_output, MD5_RESULTLEN) == 0);
+
+       /* single byte at a time */
+       md5_init(&md5_ctx);
+       memset(&ctx, 0, sizeof(ctx));
+       for (unsigned int i = 0; i < sizeof(test_input)-1; i++) {
+               message_header_hash_more(&ctx, &hash_method_md5, &md5_ctx, 2,
+                                        test_input + i, 1);
+       }
+       md5_final(&md5_ctx, md5_input);
+       test_assert(memcmp(md5_input, md5_output, MD5_RESULTLEN) == 0);
+
        test_end();
 }
 
index 05138bf318703adc0b74c9a358d2490beb440c94..8b773ba57d504c62c3a8e6f6e28eea336fab40ba 100644 (file)
@@ -181,6 +181,7 @@ int pop3_migration_get_hdr_sha1(uint32_t mail_seq, struct istream *input,
 {
        const unsigned char *data;
        size_t size;
+       struct message_header_hash_context hash_ctx;
        struct sha1_ctxt sha1_ctx;
        struct pop3_hdr_context hdr_ctx;
 
@@ -194,7 +195,7 @@ int pop3_migration_get_hdr_sha1(uint32_t mail_seq, struct istream *input,
 
        sha1_init(&sha1_ctx);
        while (i_stream_read_data(input, &data, &size, 0) > 0) {
-               message_header_hash_more(&hash_method_sha1, &sha1_ctx, 2,
+               message_header_hash_more(&hash_ctx, &hash_method_sha1, &sha1_ctx, 2,
                                         data, size);
                i_stream_skip(input, size);
        }