This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] locale: Avoid zero-length array in _nl_category_names [BZ #24962]
- From: Florian Weimer <fweimer at redhat dot com>
- To: libc-alpha at sourceware dot org
- Cc: Martin Sebor <msebor at redhat dot com>
- Date: Thu, 05 Sep 2019 09:34:04 +0200
- Subject: [PATCH] locale: Avoid zero-length array in _nl_category_names [BZ #24962]
(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 <fweimer@redhat.com>
[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.
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;