]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-fts: Fix assert-crash in fts_icu_lcase()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 24 Jan 2017 15:18:07 +0000 (17:18 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 30 Jan 2017 09:47:11 +0000 (11:47 +0200)
Fixes:
Panic: file fts-icu.c: line 152 (fts_icu_lcase): assertion failed: (err != U_BUFFER_OVERFLOW_ERROR)

src/lib-fts/fts-icu.c
src/lib-fts/test-fts-icu.c

index b49ad1738efdb6cba209a388cb14e48e91d9dbca..1869f19264690740e3944f745ab1d0b6f2a2540b 100644 (file)
@@ -142,14 +142,17 @@ void fts_icu_lcase(string_t *dest_utf8, const char *src_utf8)
        avail_bytes = buffer_get_writable_size(dest_utf8) - dest_pos;
        dest_data = buffer_get_space_unsafe(dest_utf8, dest_pos, avail_bytes);
 
-       dest_full_len = ucasemap_utf8ToLower(csm, dest_data, avail_bytes,
-                                            src_utf8, -1, &err);
-       if (err == U_BUFFER_OVERFLOW_ERROR) {
+       /* ucasemap_utf8ToLower() may need to be called multiple times, because
+          the first return value may not be large enough. */
+       for (unsigned int i = 0;; i++) {
+               dest_full_len = ucasemap_utf8ToLower(csm, dest_data, avail_bytes,
+                                                    src_utf8, -1, &err);
+               if (err != U_BUFFER_OVERFLOW_ERROR || i == 2)
+                       break;
+
                err = U_ZERO_ERROR;
                dest_data = buffer_get_space_unsafe(dest_utf8, dest_pos, dest_full_len);
-               dest_full_len = ucasemap_utf8ToLower(csm, dest_data, dest_full_len,
-                                                    src_utf8, -1, &err);
-               i_assert(err != U_BUFFER_OVERFLOW_ERROR);
+               avail_bytes = dest_full_len;
        }
        if (U_FAILURE(err)) {
                i_fatal("LibICU ucasemap_utf8ToLower() failed: %s",
index 47d5a45ed27759241e7fed814ee747eef675f311..4ba753b17f8f48d6ec4f7f1da573c0ef6847ec8c 100644 (file)
@@ -169,6 +169,16 @@ static void test_fts_icu_lcase_resize(void)
        test_end();
 }
 
+static void test_fts_icu_lcase_resize_invalid_utf8(void)
+{
+       string_t *dest;
+
+       test_begin("fts_icu_lcase resize invalid utf8");
+       dest = t_str_new(1);
+       fts_icu_lcase(dest, ".\x80.");
+       test_end();
+}
+
 int main(void)
 {
        static void (*test_functions[])(void) = {
@@ -180,6 +190,7 @@ int main(void)
                test_fts_icu_translate_resize,
                test_fts_icu_lcase,
                test_fts_icu_lcase_resize,
+               test_fts_icu_lcase_resize_invalid_utf8,
                NULL
        };
        int ret = test_run(test_functions);