]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: unicode-transform: Fix assert crash in NFx normalizer occurring at very long...
authorStephan Bosch <stephan.bosch@open-xchange.com>
Fri, 6 Mar 2026 18:58:25 +0000 (19:58 +0100)
committerStephan Bosch <stephan.bosch@open-xchange.com>
Wed, 11 Mar 2026 10:17:33 +0000 (11:17 +0100)
src/lib/test-unicode-nf.c
src/lib/unicode-transform.c

index e7805f8aa95ee5d1f077cf76e0601e7ea6374c30..ed332a7f113a4899d6a14cc6856d9e8c614a785f 100644 (file)
@@ -425,7 +425,7 @@ static void test_long(void)
        test_assert_strcmp(nfkd, str_c(nf_out));
 }
 
-static void test_stream_safe(void)
+static void test_stream_safe(bool compose)
 {
        /* UAX15, Section 13:
 
@@ -468,7 +468,10 @@ static void test_stream_safe(void)
 
        int ret;
 
-       ret = uni_utf8_write_nfd(str_data(in), str_len(in), nf_out);
+       if (compose)
+               ret = uni_utf8_write_nfc(str_data(in), str_len(in), nf_out);
+       else
+               ret = uni_utf8_write_nfd(str_data(in), str_len(in), nf_out);
        test_assert(ret == 0);
 
        /* Check the result */
@@ -518,7 +521,10 @@ static void test_stream_safe(void)
 
        /* Apply NFD normalization */
 
-       ret = uni_utf8_write_nfd(str_data(in), str_len(in), nf_out);
+       if (compose)
+               ret = uni_utf8_write_nfc(str_data(in), str_len(in), nf_out);
+       else
+               ret = uni_utf8_write_nfd(str_data(in), str_len(in), nf_out);
        test_assert(ret == 0);
 
        /* Check the result */
@@ -557,6 +563,23 @@ static void test_stream_safe(void)
        test_assert(nf_data[415] == '3');                       /* digit 3 */
 }
 
+static void test_full_buffer(bool compose)
+{
+       static const char input[] =
+               "\x20\xeb\x92\x92\xcd\x84\xcd\x84\xcd\x84\xcd\x84\xcd\x84"
+               "\xcd\x84\xcd\x84\xcd\x84\xcd\x84\xcc\x9a\xcd\x84\xcd\x84"
+               "\xcd\x84\xcd\x84\xcd\x84\xcd\x84";
+
+       buffer_t *nf_out = t_buffer_create(1024);
+       int ret;
+
+       if (compose)
+               ret = uni_utf8_write_nfc(input, sizeof(input) - 1, nf_out);
+       else
+               ret = uni_utf8_write_nfd(input, sizeof(input) - 1, nf_out);
+       test_assert(ret == 0);
+}
+
 void test_unicode_nf(void)
 {
        struct istream *input = NULL;
@@ -621,7 +644,18 @@ void test_unicode_nf(void)
        test_end();
 
        /* Test Stream Safe algorithm (UAX15-D4) */
-       test_begin("unicode normalization: stream safe");
-       test_stream_safe();
+       test_begin("unicode normalization: stream safe (nfd)");
+       test_stream_safe(FALSE);
+       test_end();
+       test_begin("unicode normalization: stream safe (nfc)");
+       test_stream_safe(TRUE);
+       test_end();
+
+       /* Test buffer assertions */
+       test_begin("unicode normalization: full buffer (nfd)");
+       test_full_buffer(FALSE);
+       test_end();
+       test_begin("unicode normalization: full buffer (nfc)");
+       test_full_buffer(TRUE);
        test_end();
 }
index 0fe272d6861e1776233ca76ec6e73589c6d3f5fb..d6dc6b3adc24c5727af154b41b81cf72f27c7d86 100644 (file)
@@ -373,6 +373,12 @@ unicode_nf_cp(struct unicode_nf_context *ctx, uint32_t cp,
        uint8_t nf_qc_mask = ctx->nf_qc_mask;
        size_t i;
 
+       i_assert(ctx->buffer_len <= buffer_size);
+       if (ctx->buffer_len == buffer_size) {
+               /* Buffer already full */
+               return FALSE;
+       }
+
        /*
         * Decompose the code point
         */