Properly handle broken setlocale(LC_ALL, NULL)

Early AIX versions could return a truncated value in this case.
https://www.ibm.com/support/pages/apar/IV22097

Tests were skipped as a result by
59b4d2932ceb16662879bca2a22315c3597276ae.

This commit adds an easy workaround for this bug, changes the AIX hints
file to enable it; the next commit will revert the test skipping.
This commit is contained in:
Karl Williamson 2023-06-13 11:24:27 -06:00
parent 4b99cd024b
commit 28b5b3c676
2 changed files with 36 additions and 2 deletions

View File

@ -694,5 +694,10 @@ EOF
;;
esac # not gcc
case "$osvers" in
[1-6].*) # The setlocale() return can be wrongly truncated
ccflags="$ccflags -DHAS_BROKEN_SETLOCALE_QUERY_LC_ALL"
;;
esac
# EOF

View File

@ -243,6 +243,13 @@
* querylocale() is called only while the locale mutex is locked, and
* the result is copied to a per-thread place before unlocking.
*
* -Accflags=-DHAS_BROKEN_SETLOCALE_QUERY_LC_ALL
* This would be set in a hints file to tell perl that doing a libc
* setlocale(LC_ALL, NULL)
* can give erroneous results, and perl will compensate to get the
* correct results. This is known to be a problem in earlier AIX
* versions
*
* -Accflags=-DHAS_LF_IN_SETLOCALE_RETURN
* This would be set in a hints file to tell perl that a libc
* setlocale() can return results containing \n characters that need
@ -1175,14 +1182,18 @@ S_parse_LC_ALL_string(pTHX_ const char * string,
* Any necessary mutex locking needs to be done at a higher level.
*
* On most platforms this layer is empty, expanding to just the layer
* below. To enable it, call Configure with:
* below. To enable it, call Configure with either or both:
* -Accflags=-DHAS_LF_IN_SETLOCALE_RETURN
* to indicate that extraneous \n characters can be returned
* by setlocale()
* -Accflags=-DHAS_BROKEN_SETLOCALE_QUERY_LC_ALL
* to indicate that setlocale(LC_ALL, NULL) cannot be relied
* on
*/
#if ! defined(USE_LOCALE) \
|| ! defined(HAS_LF_IN_SETLOCALE_RETURN)
|| ! ( defined(HAS_LF_IN_SETLOCALE_RETURN) \
|| defined(HAS_BROKEN_SETLOCALE_QUERY_LC_ALL))
# define stdized_setlocale(cat, locale) posix_setlocale(cat, locale)
# define stdize_locale(cat, locale) (locale)
#else
@ -1206,6 +1217,8 @@ S_stdize_locale(pTHX_ const int category,
*
* The current things this corrects are:
* 1) A new-line. This function chops any \n characters
* 2) A broken 'setlocale(LC_ALL, foo)' This constructs a proper returned
* string from the constituent categories
*
* If no changes were made, the input is returned as-is */
@ -1219,6 +1232,21 @@ S_stdize_locale(pTHX_ const int category,
}
char * retval = (char *) input_locale;
# if defined(LC_ALL) && defined(HAS_BROKEN_SETLOCALE_QUERY_LC_ALL)
/* If setlocale(LC_ALL, NULL) is broken, compute what the system
* actually thinks it should be from its individual components */
if (category == LC_ALL) {
retval = (char *) calculate_LC_ALL_string(
NULL, /* query each individ locale */
EXTERNAL_FORMAT_FOR_SET,
caller_line);
}
# endif
# ifdef HAS_NL_IN_SETLOCALE_RETURN
char * first_bad = NULL;
# ifndef LC_ALL
@ -1316,6 +1344,7 @@ S_stdize_locale(pTHX_ const int category,
# endif
# undef INPUT_LOCALE
# undef MARK_CHANGED
# endif /* HAS_NL_IN_SETLOCALE_RETURN */
return (const char *) retval;
}