From: Bo Anderson Date: Wed, 7 Aug 2024 02:14:57 +0000 (+0100) Subject: idn: support non-UTF-8 input under AppleIDN X-Git-Tag: curl-8_10_0~342 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a35687831f51626fb393d7af9a8154c727db626d;p=thirdparty%2Fcurl.git idn: support non-UTF-8 input under AppleIDN This aligns the behaviour with libidn2 and the curl documentation. Closes #14431 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 7242d687fc..7427516898 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -980,7 +980,7 @@ if(APPLE) check_symbol_exists("uidna_openUTS46" "unicode/uidna.h" HAVE_APPLE_IDN) cmake_pop_check_state() if(HAVE_APPLE_IDN) - list(APPEND CURL_LIBS "icucore") + list(APPEND CURL_LIBS "icucore" "iconv") else() set(USE_APPLE_IDN OFF) endif() diff --git a/configure.ac b/configure.ac index 1e7a9bba72..d81167a851 100644 --- a/configure.ac +++ b/configure.ac @@ -2780,7 +2780,7 @@ case $host_os in AC_DEFINE(USE_APPLE_IDN, 1, [if AppleIDN]) AC_SUBST(USE_APPLE_IDN, [1]) AC_SUBST([IDN_ENABLED], [1]) - LIBS="-licucore $LIBS" + LIBS="-licucore -liconv $LIBS" ) ]) ;; diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS index 9555e42058..cc5f1dd289 100644 --- a/docs/KNOWN_BUGS +++ b/docs/KNOWN_BUGS @@ -530,7 +530,7 @@ problems may have been fixed or changed somewhat since this was written. 11.7 AppleIDN test failures - Test 1034 and 1035 fail on macOS when built to use AppleIDN. + Test 1035 fail on macOS when built to use AppleIDN. See https://github.com/curl/curl/issues/14176 diff --git a/lib/idn.c b/lib/idn.c index ef55ddfec0..b1c1fcaa62 100644 --- a/lib/idn.c +++ b/lib/idn.c @@ -53,30 +53,70 @@ /* for macOS and iOS targets */ #if defined(USE_APPLE_IDN) #include +#include +#include #define MAX_HOST_LENGTH 512 +static CURLcode iconv_to_utf8(const char *in, size_t inlen, + char **out, size_t *outlen) +{ + iconv_t cd = iconv_open("UTF-8", nl_langinfo(CODESET)); + if(cd != (iconv_t)-1) { + size_t iconv_outlen = *outlen; + char *iconv_in = (char *)in; + size_t iconv_inlen = inlen; + size_t iconv_result = iconv(cd, &iconv_in, &iconv_inlen, + out, &iconv_outlen); + *outlen -= iconv_outlen; + iconv_close(cd); + if(iconv_result == (size_t)-1) { + if(errno == ENOMEM) + return CURLE_OUT_OF_MEMORY; + else + return CURLE_URL_MALFORMAT; + } + + return CURLE_OK; + } + else { + if(errno == ENOMEM) + return CURLE_OUT_OF_MEMORY; + else + return CURLE_FAILED_INIT; + } +} + static CURLcode mac_idn_to_ascii(const char *in, char **out) { size_t inlen = strlen(in); if(inlen < MAX_HOST_LENGTH) { - UErrorCode err = U_ZERO_ERROR; - UIDNA* idna = uidna_openUTS46( - UIDNA_CHECK_BIDI|UIDNA_NONTRANSITIONAL_TO_ASCII, &err); - if(!U_FAILURE(err)) { - UIDNAInfo info = UIDNA_INFO_INITIALIZER; - char buffer[MAX_HOST_LENGTH] = {0}; - (void)uidna_nameToASCII_UTF8(idna, in, -1, buffer, - sizeof(buffer) - 1, &info, &err); - uidna_close(idna); + char iconv_buffer[MAX_HOST_LENGTH] = {0}; + char *iconv_outptr = iconv_buffer; + size_t iconv_outlen = sizeof(iconv_buffer); + CURLcode iconv_result = iconv_to_utf8(in, inlen, + &iconv_outptr, &iconv_outlen); + if(!iconv_result) { + UErrorCode err = U_ZERO_ERROR; + UIDNA* idna = uidna_openUTS46( + UIDNA_CHECK_BIDI|UIDNA_NONTRANSITIONAL_TO_ASCII, &err); if(!U_FAILURE(err)) { - *out = strdup(buffer); - if(*out) - return CURLE_OK; - else - return CURLE_OUT_OF_MEMORY; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + char buffer[MAX_HOST_LENGTH] = {0}; + (void)uidna_nameToASCII_UTF8(idna, iconv_buffer, (int)iconv_outlen, + buffer, sizeof(buffer) - 1, &info, &err); + uidna_close(idna); + if(!U_FAILURE(err)) { + *out = strdup(buffer); + if(*out) + return CURLE_OK; + else + return CURLE_OUT_OF_MEMORY; + } } } + else + return iconv_result; } return CURLE_URL_MALFORMAT; } diff --git a/tests/data/DISABLED b/tests/data/DISABLED index 02593cde0d..0e6c79767a 100644 --- a/tests/data/DISABLED +++ b/tests/data/DISABLED @@ -94,7 +94,6 @@ 313 %endif %if AppleIDN -1034 1035 %endif %if WinIDN