]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-charset: Fixed assert-crash with some iconv() versions.
authorTimo Sirainen <tss@iki.fi>
Tue, 8 Sep 2015 10:07:59 +0000 (13:07 +0300)
committerTimo Sirainen <tss@iki.fi>
Tue, 8 Sep 2015 10:07:59 +0000 (13:07 +0300)
Older glibc iconv() versions seem to skip over invalid characters, at least
with some charsets, while newer versions don't. We were assuming that the
skipping never happened, so if the invalid character was at the end of the
string we could have wrapped size to (size_t)-1 and caused a crash later on.

src/lib-charset/charset-iconv.c
src/lib-charset/test-charset.c

index 431f226ac11513a429fdf90c3b77807e2edce7d8..6bc6bcf938f5e4feb50a384f7fe67d60fd23edcb 100644 (file)
@@ -111,6 +111,7 @@ charset_to_utf8(struct charset_translation *t,
        bool ret;
 
        for (pos = 0;;) {
+               i_assert(pos <= *src_size);
                size = *src_size - pos;
                ret = charset_to_utf8_try(t, src + pos, &size, dest, &result);
                pos += size;
@@ -124,7 +125,8 @@ charset_to_utf8(struct charset_translation *t,
                                              strlen(UNICODE_REPLACEMENT_CHAR_UTF8));
                                prev_invalid_pos = dest->used;
                        }
-                       pos++;
+                       if (pos < *src_size)
+                               pos++;
                }
        }
 
index ba97be51c8581ab25e8956fbd587037aca790508..ce91a612804c980ebbf725a2b909eef2df0a2a3b 100644 (file)
@@ -85,6 +85,28 @@ static void test_charset_iconv(void)
        test_charset_utf8_common("UTF-8//IGNORE");
        test_end();
 }
+static void test_charset_iconv_crashes(void)
+{
+       struct {
+               const char *charset;
+               const char *input;
+       } tests[] = {
+               { "CP932", "\203\334" }
+       };
+       string_t *str = t_str_new(128);
+       enum charset_result result;
+       unsigned int i;
+
+       test_begin("charset iconv crashes");
+       for (i = 0; i < N_ELEMENTS(tests); i++) {
+               str_truncate(str, 0);
+               /* we don't care about checking the result. we only want to
+                  verify that there's no crash. */
+               (void)charset_to_utf8_str(tests[i].charset, NULL,
+                                         tests[i].input, str, &result);
+       }
+       test_end();
+}
 #endif
 
 int main(void)
@@ -94,6 +116,7 @@ int main(void)
                test_charset_utf8,
 #ifdef HAVE_ICONV
                test_charset_iconv,
+               test_charset_iconv_crashes,
 #endif
                NULL
        };