changeset 21449:3909e522e8af

lib-fts: Fix assert-crash in fts_icu_lcase() Fixes: Panic: file fts-icu.c: line 152 (fts_icu_lcase): assertion failed: (err != U_BUFFER_OVERFLOW_ERROR)
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Tue, 24 Jan 2017 17:18:07 +0200
parents 66253aee7ebf
children 5ca3a3f11254
files src/lib-fts/fts-icu.c src/lib-fts/test-fts-icu.c
diffstat 2 files changed, 20 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-fts/fts-icu.c	Fri Jan 27 09:41:36 2017 +0200
+++ b/src/lib-fts/fts-icu.c	Tue Jan 24 17:18:07 2017 +0200
@@ -142,14 +142,17 @@
 	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",
--- a/src/lib-fts/test-fts-icu.c	Fri Jan 27 09:41:36 2017 +0200
+++ b/src/lib-fts/test-fts-icu.c	Tue Jan 24 17:18:07 2017 +0200
@@ -169,6 +169,16 @@
 	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 @@
 		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);