From 92bfe2a2e44184f62d4093ac51fb8cf5d951a1d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20R=C3=BChsen?= Date: Sun, 16 Apr 2017 19:55:14 +0200 Subject: [PATCH] Fix charset transcoding issue for non-reversible codepoints * src/url.c: Check iconv() against 0, not -1 On some libiconv implementations, unknown codepoints become encoded as ?, e.g. when converting a non-ascii codepoint to ASCII. This results in ambigious file names which also fails our tests. --- gnulib | 2 +- src/url.c | 83 +++++++++++++++++++++++++++++-------------------------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/gnulib b/gnulib index 683b6078..f497bc10 160000 --- a/gnulib +++ b/gnulib @@ -1 +1 @@ -Subproject commit 683b6078961f10905baba598c469402ed0133425 +Subproject commit f497bc109ac365359ce499aeaef74f39c7e4e8c7 diff --git a/src/url.c b/src/url.c index 7f2376ff..4aaef63b 100644 --- a/src/url.c +++ b/src/url.c @@ -1567,9 +1567,9 @@ convert_fname (char *fname) to_encoding = nl_langinfo (CODESET); cd = iconv_open (to_encoding, from_encoding); - if (cd == (iconv_t)(-1)) - logprintf (LOG_VERBOSE, _("Conversion from %s to %s isn't supported\n"), - quote (from_encoding), quote (to_encoding)); + if (cd == (iconv_t) (-1)) + logprintf (LOG_VERBOSE, _ ("Conversion from %s to %s isn't supported\n"), + quote (from_encoding), quote (to_encoding)); else { inlen = strlen (fname); @@ -1578,44 +1578,49 @@ convert_fname (char *fname) done = 0; for (;;) - { - if (iconv (cd, (ICONV_CONST char **) &fname, &inlen, &s, &outlen) != (size_t)(-1) - && iconv (cd, NULL, NULL, &s, &outlen) != (size_t)(-1)) - { - *(converted_fname + len - outlen - done) = '\0'; - iconv_close(cd); - DEBUGP (("Converted file name '%s' (%s) -> '%s' (%s)\n", - orig_fname, from_encoding, converted_fname, to_encoding)); - xfree (orig_fname); - return converted_fname; - } + { + errno = 0; + if (iconv (cd, (ICONV_CONST char **) &fname, &inlen, &s, &outlen) == 0 + && iconv (cd, NULL, NULL, &s, &outlen) == 0) + { + *(converted_fname + len - outlen - done) = '\0'; + iconv_close (cd); + DEBUGP (("Converted file name '%s' (%s) -> '%s' (%s)\n", + orig_fname, from_encoding, converted_fname, to_encoding)); + xfree (orig_fname); + return converted_fname; + } - /* Incomplete or invalid multibyte sequence */ - if (errno == EINVAL || errno == EILSEQ) - { - logprintf (LOG_VERBOSE, - _("Incomplete or invalid multibyte sequence encountered\n")); - xfree (converted_fname); - converted_fname = (char *)orig_fname; - break; - } - else if (errno == E2BIG) /* Output buffer full */ - { - done = len; - len = outlen = done + inlen * 2; - converted_fname = xrealloc (converted_fname, outlen + 1); - s = converted_fname + done; - } - else /* Weird, we got an unspecified error */ - { - logprintf (LOG_VERBOSE, _("Unhandled errno %d\n"), errno); - xfree (converted_fname); - converted_fname = (char *)orig_fname; - break; - } - } + /* Incomplete or invalid multibyte sequence */ + if (errno == EINVAL || errno == EILSEQ || errno == 0) + { + if (errno) + logprintf (LOG_VERBOSE, + _ ("Incomplete or invalid multibyte sequence encountered\n")); + else + logprintf (LOG_VERBOSE, + _ ("Unconvertable multibyte sequence encountered\n")); + xfree (converted_fname); + converted_fname = (char *) orig_fname; + break; + } + else if (errno == E2BIG) /* Output buffer full */ + { + done = len; + len = outlen = done + inlen * 2; + converted_fname = xrealloc (converted_fname, outlen + 1); + s = converted_fname + done; + } + else /* Weird, we got an unspecified error */ + { + logprintf (LOG_VERBOSE, _ ("Unhandled errno %d\n"), errno); + xfree (converted_fname); + converted_fname = (char *) orig_fname; + break; + } + } DEBUGP (("Failed to convert file name '%s' (%s) -> '?' (%s)\n", - orig_fname, from_encoding, to_encoding)); + orig_fname, from_encoding, to_encoding)); } iconv_close(cd);