From: Stephan Bosch Date: Wed, 16 Sep 2020 03:06:12 +0000 (+0200) Subject: lib-mail: test-message-header-decode - Add random encode/decode tests for 8 bit data. X-Git-Tag: 2.3.13~105 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8608c269084f5376e3191be87602c2bbb6905466;p=thirdparty%2Fdovecot%2Fcore.git lib-mail: test-message-header-decode - Add random encode/decode tests for 8 bit data. This also tests handling of (broken) UTF-8 input. --- diff --git a/src/lib-mail/test-message-header-decode.c b/src/lib-mail/test-message-header-decode.c index 8ac9f9fdde..7934c7bf61 100644 --- a/src/lib-mail/test-message-header-decode.c +++ b/src/lib-mail/test-message-header-decode.c @@ -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)