>From dac3fc8a25bbc43a2c231dfb8c41b4fd6c55a8a5 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 14 Sep 2026 18:09:27 -0400 Subject: [PATCH 09/18] locale: make explicit request of unavailable locales fail have __get_locale track whether the request is implicit (obtained via environment for an argument of "") or explicit. if explicit, names that fail to resove to a locale file will produce a return value of LOC_MAP_FAILED, which setlocale and newlocale already interpret as an error condition. if implicit, return C.UTF-8 for LC_CTYPE, and otherwise a null pointer (interpreted as C locale). to avoid breaking explicit requests intending to get the C.UTF-8 locale, the matching is relaxed so that C.* and POSIX.* are interpreted as C.UTF-8. this is mainly to catch C.utf8 or other spellings without having to enumerate any possibility someone might come up with. --- src/locale/locale_map.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/locale/locale_map.c b/src/locale/locale_map.c index ce56bc40..9ebf7ced 100644 --- a/src/locale/locale_map.c +++ b/src/locale/locale_map.c @@ -39,8 +39,10 @@ const struct __locale_map *__get_locale(int cat, const char *val) const char *path = 0, *z; char buf[256]; size_t l, n; + int implicit = 0; if (!*val) { + implicit = 1; (val = getenv("LC_ALL")) && *val || (val = getenv(envvars[cat])) && *val || (val = getenv("LANG")) && *val || @@ -49,16 +51,12 @@ const struct __locale_map *__get_locale(int cat, const char *val) /* Limit name length and forbid leading dot or any slashes. */ for (n=0; nnext) if (!strcmp(val, p->name)) return p; @@ -92,9 +90,10 @@ const struct __locale_map *__get_locale(int cat, const char *val) } } - /* For LC_CTYPE, never return a null pointer unless the - * requested name was "C" or "POSIX". */ - if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8; - - return new; + if (new) return new; +fail: + if (!implicit) return LOC_MAP_FAILED; +utf8: + if (cat==LC_CTYPE) return &__c_dot_utf8; + return 0; } -- 2.21.0