From patchwork Thu Sep 5 07:34:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 34389 Received: (qmail 92405 invoked by alias); 5 Sep 2019 07:34:12 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 92105 invoked by uid 89); 5 Sep 2019 07:34:12 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=Individual, H*Ad:U*msebor X-HELO: mx1.redhat.com From: Florian Weimer To: libc-alpha@sourceware.org Cc: Martin Sebor Subject: [PATCH] locale: Avoid zero-length array in _nl_category_names [BZ #24962] Date: Thu, 05 Sep 2019 09:34:04 +0200 Message-ID: <87a7bjkxhv.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux) MIME-Version: 1.0 (Martin, can you give this a test using GCC 10? I don't expect any issues because the zero-length array is completely gone. The patch passed testing on x86_64-linux-gnu without regressions, but with GCC 9.) The union wrapper is unnecessary because C allows to read any object as a sequence of chars. 2019-09-05 Florian Weimer [BZ #24962] * locale/localeinfo.h (_nl_category_names): Remove union wrapper. (_nl_category_names_get): New function. * intl/dcigettext.c (category_to_name): Call it. * locale/findlocale.c (_nl_find_locale): Likewise. * intl/loadlocale.c (_nl_load_locale): Likewise. * locale/newlocale.c (__newlocale): Likewise. * locale/setlocale.c (_nl_category_names): Adjust definition. (_nl_category_name_idxs): Likewise. (new_composite_name): Call _nl_category_names_get. (setlocale): Likewise. Reviewed-by: Carlos O'Donell diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 4df93e2a8e..11f3749457 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -360,8 +360,7 @@ static const char *guess_category_value (int category, #ifdef _LIBC # include "../locale/localeinfo.h" -# define category_to_name(category) \ - _nl_category_names.str + _nl_category_name_idxs[category] +# define category_to_name(category) _nl_category_names_get (category) #else static const char *category_to_name (int category); #endif diff --git a/locale/findlocale.c b/locale/findlocale.c index 9af605bd64..28b0226265 100644 --- a/locale/findlocale.c +++ b/locale/findlocale.c @@ -118,8 +118,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len, variables. */ cloc_name = getenv ("LC_ALL"); if (!name_present (cloc_name)) - cloc_name = getenv (_nl_category_names.str - + _nl_category_name_idxs[category]); + cloc_name = getenv (_nl_category_names_get (category)); if (!name_present (cloc_name)) cloc_name = getenv ("LANG"); if (!name_present (cloc_name)) @@ -207,8 +206,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len, locale_path, locale_path_len, mask, language, territory, codeset, normalized_codeset, modifier, - _nl_category_names.str - + _nl_category_name_idxs[category], 0); + _nl_category_names_get (category), 0); if (locale_file == NULL) { @@ -218,8 +216,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len, locale_path, locale_path_len, mask, language, territory, codeset, normalized_codeset, modifier, - _nl_category_names.str - + _nl_category_name_idxs[category], 1); + _nl_category_names_get (category), 1); if (locale_file == NULL) /* This means we are out of core. */ return NULL; diff --git a/locale/loadlocale.c b/locale/loadlocale.c index 571c94e1de..ff578f6416 100644 --- a/locale/loadlocale.c +++ b/locale/loadlocale.c @@ -199,8 +199,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category) newp = (char *) alloca (filenamelen + 5 + _nl_category_name_sizes[category] + 1); __mempcpy (__mempcpy (__mempcpy (newp, file->filename, filenamelen), - "/SYS_", 5), - _nl_category_names.str + _nl_category_name_idxs[category], + "/SYS_", 5), _nl_category_names_get (category), _nl_category_name_sizes[category] + 1); fd = __open_nocancel (newp, O_RDONLY | O_CLOEXEC); diff --git a/locale/localeinfo.h b/locale/localeinfo.h index 7c1cc3eecb..0e2a0d7e49 100644 --- a/locale/localeinfo.h +++ b/locale/localeinfo.h @@ -183,23 +183,29 @@ enum #define _ISCTYPE(c, desc) \ (((((const uint32_t *) (desc)) - 8)[(c) >> 5] >> ((c) & 0x1f)) & 1) -/* Category name handling variables. */ +/* Category name handling variables. Concatenate all the strings in a + single object to minimize relocations. Individual strings can be + accessed using _nl_category_names. */ #define CATNAMEMF(line) CATNAMEMF1 (line) #define CATNAMEMF1(line) str##line -extern const union catnamestr_t +extern const struct catnamestr_t { - struct - { #define DEFINE_CATEGORY(category, category_name, items, a) \ - char CATNAMEMF (__LINE__)[sizeof (category_name)]; + char CATNAMEMF (__LINE__)[sizeof (category_name)]; #include "categories.def" #undef DEFINE_CATEGORY - }; - char str[0]; } _nl_category_names attribute_hidden; extern const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden; extern const uint8_t _nl_category_name_sizes[__LC_LAST] attribute_hidden; +/* Return the name of the category INDEX, which must be nonnegative + and less than _LC_LAST. */ +static inline const char * +_nl_category_names_get (int index) +{ + return (const char *) &_nl_category_names + _nl_category_name_idxs[index]; +} + /* Name of the standard locales. */ extern const char _nl_C_name[] attribute_hidden; extern const char _nl_POSIX_name[] attribute_hidden; diff --git a/locale/newlocale.c b/locale/newlocale.c index 8c5960a45d..561244245b 100644 --- a/locale/newlocale.c +++ b/locale/newlocale.c @@ -131,8 +131,7 @@ __newlocale (int category_mask, const char *locale, locale_t base) for (cnt = 0; cnt < __LC_LAST; ++cnt) if (cnt != LC_ALL && (size_t) (cp - np) == _nl_category_name_sizes[cnt] - && memcmp (np, (_nl_category_names.str - + _nl_category_name_idxs[cnt]), cp - np) == 0) + && memcmp (np, (_nl_category_names_get (cnt)), cp - np) == 0) break; if (cnt == __LC_LAST) diff --git a/locale/setlocale.c b/locale/setlocale.c index 9bd35454b9..264a1ecba7 100644 --- a/locale/setlocale.c +++ b/locale/setlocale.c @@ -65,20 +65,18 @@ static char *const _nl_current_used[] = /* Define an array of category names (also the environment variable names). */ -const union catnamestr_t _nl_category_names attribute_hidden = +const struct catnamestr_t _nl_category_names attribute_hidden = { - { #define DEFINE_CATEGORY(category, category_name, items, a) \ - category_name, + category_name, #include "categories.def" #undef DEFINE_CATEGORY - } }; const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden = { #define DEFINE_CATEGORY(category, category_name, items, a) \ - [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)), + [category] = offsetof (struct catnamestr_t, CATNAMEMF (__LINE__)), #include "categories.def" #undef DEFINE_CATEGORY }; @@ -180,7 +178,7 @@ new_composite_name (int category, const char *newnames[__LC_LAST]) const char *name = (category == LC_ALL ? newnames[i] : category == i ? newnames[0] : _nl_global_locale.__names[i]); - p = __stpcpy (p, _nl_category_names.str + _nl_category_name_idxs[i]); + p = __stpcpy (p, _nl_category_names_get (i)); *p++ = '='; p = __stpcpy (p, name); *p++ = ';'; @@ -298,8 +296,7 @@ setlocale (int category, const char *locale) for (cnt = 0; cnt < __LC_LAST; ++cnt) if (cnt != LC_ALL && (size_t) (cp - np) == _nl_category_name_sizes[cnt] - && (memcmp (np, (_nl_category_names.str - + _nl_category_name_idxs[cnt]), cp - np) + && (memcmp (np, (_nl_category_names_get (cnt)), cp - np) == 0)) break;