]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: test-message-header-decode - Add random encode/decode tests for 8 bit data.
authorStephan Bosch <stephan.bosch@open-xchange.com>
Wed, 16 Sep 2020 03:06:12 +0000 (05:06 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Wed, 7 Oct 2020 14:08:11 +0000 (14:08 +0000)
This also tests handling of (broken) UTF-8 input.

src/lib-mail/test-message-header-decode.c

index 8ac9f9fdde9b4a83e9854eab821bdaffa640cef6..7934c7bf61d519aeb1a63d79220af7245caf6e83 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "buffer.h"
 #include "str.h"
+#include "randgen.h"
 #include "charset-utf8.h"
 #include "message-header-encode.h"
 #include "message-header-decode.h"
@@ -87,13 +88,71 @@ static void check_encoded(string_t *encoded, unsigned int test_idx)
        test_assert_idx(cur_line_len <= 76, test_idx);
 }
 
+static void
+check_encode_decode_result(const unsigned char *inbuf, size_t inbuf_len,
+                          string_t *out, unsigned int test_idx)
+{
+       static const unsigned char *rep_char =
+               (const unsigned char *)UNICODE_REPLACEMENT_CHAR_UTF8;
+       static const unsigned int rep_char_len =
+               UNICODE_REPLACEMENT_CHAR_UTF8_LEN;
+       const unsigned char *outbuf = str_data(out);
+       size_t outbuf_len = str_len(out);
+       const unsigned char *pin, *pinend, *pout, *poutend;
+       bool invalid_char = FALSE;
+
+       if (test_has_failed())
+               return;
+
+       pin = inbuf;
+       pinend = inbuf + inbuf_len;
+       pout = outbuf;
+       poutend = outbuf + outbuf_len;
+
+       while (pin < pinend) {
+               unichar_t ch;
+               int nch;
+
+               nch = uni_utf8_get_char_n(pin, pinend - pin, &ch);
+               if (nch <= 0) {
+                       /* Invalid character; check proper substitution of
+                          replacement character in encoded/decoded output. */
+                       pin++;
+                       if (!invalid_char) {
+                               /* Only one character is substituted for a run
+                                  of bad stuff. */
+                               test_assert_idx(
+                                       (poutend - pout) >= rep_char_len &&
+                                       memcmp(pout, rep_char,
+                                              rep_char_len) == 0, test_idx);
+                               pout += rep_char_len;
+                       }
+                       invalid_char = TRUE;
+               } else {
+                       /* Valid character; check matching character bytes. */
+                       invalid_char = FALSE;
+                       test_assert_idx((pinend - pin) >= nch &&
+                                       (poutend - pout) >= nch &&
+                                       memcmp(pin, pout, nch) == 0, test_idx);
+                       pin += nch;
+                       pout += nch;
+               }
+
+               if (test_has_failed())
+                       return;
+       }
+
+       /* Both buffers must have reached the end now. */
+       test_assert_idx(pin == pinend && pout == poutend, test_idx);
+}
+
 static void test_message_header_decode_encode_random(void)
 {
        string_t *encoded, *decoded;
        unsigned char buf[1024];
        unsigned int i, j, buflen;
 
-       test_begin("message header encode & decode randomly");
+       test_begin("message header encode & decode randomly (7 bit)");
 
        encoded = t_str_new(256);
        decoded = t_str_new(256);
@@ -127,6 +186,34 @@ static void test_message_header_decode_encode_random(void)
                                memcmp(decoded->data, buf, buflen) == 0, i);
        }
        test_end();
+
+       test_begin("message header encode & decode randomly (8 bit)");
+
+       for (i = 0; i < 1000; i++) {
+               buflen = i_rand_limit(sizeof(buf));
+               random_fill(buf, buflen);
+
+               str_truncate(encoded, 0);
+               str_truncate(decoded, 0);
+
+               /* test Q */
+               message_header_encode_q(buf, buflen, encoded, 0);
+               check_encoded(encoded, i);
+               message_header_decode_utf8(encoded->data, encoded->used,
+                                          decoded, NULL);
+               check_encode_decode_result(buf, buflen, decoded, i);
+
+               /* test B */
+               str_truncate(encoded, 0);
+               str_truncate(decoded, 0);
+
+               message_header_encode_b(buf, buflen, encoded, 0);
+               check_encoded(encoded, i);
+               message_header_decode_utf8(encoded->data, encoded->used,
+                                          decoded, NULL);
+               check_encode_decode_result(buf, buflen, decoded, i);
+       }
+       test_end();
 }
 
 int main(void)