>From c872b7d9ba1cfc21e13a86b7c594129a39b3b576 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 2 Oct 2026 21:33:56 -0400 Subject: [PATCH 01/10] locale: make radix point character available for formatting/parsing only the single-byte characters '.' and ',' are supported for the radix point. this policy was established based on analysis of real-world locales, with the intent to avoid both the risk of buffer overflows/truncation in applications that might not account for multi-byte radix points if they were supported, and the possibility of ambiguous output that does not round-trip, e.g. if the radix point were defined to overlap with a digit or sign character. the __radixpt function is designed to have weak definitions merely returning '.' in translation units that call it, and to accept a null locale_t indicating the current locale, so that no locale lookup logic is needed in printf/strtod/scanf. as present it will be called only with an argument of 0, but the signature allows for writing _l versions of the functions that need to know the radix point without having to resort to uselocale. --- src/internal/locale_impl.h | 2 ++ src/locale/locale_map.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/internal/locale_impl.h b/src/internal/locale_impl.h index 531c74be..191f916b 100644 --- a/src/internal/locale_impl.h +++ b/src/internal/locale_impl.h @@ -24,6 +24,7 @@ struct __locale_map { const unsigned char *langinfo; const unsigned char *errors; struct collation collate[1]; + unsigned char alt_radix; }; struct __locale_struct { @@ -39,6 +40,7 @@ extern hidden const struct __locale_struct __c_dot_utf8_locale; hidden const struct __locale_map *__get_locale(int, const char *); hidden void __lconv_expand(locale_t); +hidden int __radixpt(locale_t); hidden const char *__loc_lookup(const unsigned char *, const unsigned char *, const int *, const int *); hidden const char *__mo_lookup(const void *, size_t, const char *); hidden int __loc_is_allocated(locale_t); diff --git a/src/locale/locale_map.c b/src/locale/locale_map.c index f97acb0e..2e459931 100644 --- a/src/locale/locale_map.c +++ b/src/locale/locale_map.c @@ -38,6 +38,13 @@ static int dummy_collation_init(struct collation *col, const unsigned char *coll weak_alias(dummy_collation_init, __collation_init); +int __radixpt(locale_t loc) +{ + if (!loc) loc = CURRENT_LOCALE; + if (!loc->cat[LC_NUMERIC]) return '.'; + return '.' - loc->cat[LC_NUMERIC]->alt_radix; +} + static int load_locale(struct __locale_map *l, const unsigned char *lm) { const unsigned char *root; @@ -54,6 +61,12 @@ static int load_locale(struct __locale_map *l, const unsigned char *lm) /* strerror, etc. strings */ l->errors = ikmlt_lookup(root, K_ERRORS); + /* radix point, loaded as a single bit indicating ',' vs '.' */ + static const int radix_path[] = LPATH(K_LCONV, 0); + const unsigned char *radix; + radix = ikmlt_lookup_path(root, radix_path); + l->alt_radix = (radix && radix[0] == ',' && !radix[1]) ? '.'-',' : 0; + collation_init(l->collate, ikmlt_lookup(root, K_COLLATION)); return 0; -- 2.21.0