[PATCH v2 4/4] ctype: Fallback initialization of TLS using relocations (bug 19341, bug 32483)
Frederic Berat
fberat@redhat.com
Fri May 16 10:52:30 GMT 2025
Le 20/12/2024 à 07:16, Florian Weimer a écrit :
> This ensures that the ctype data pointers in TLS are valid
> in secondary namespaces even without initialization via
> __ctype_init.
The fix makes sense and I confirm that the test reproduces the failure
without the fix and is not failing once the fix is applied.
Tested on x86_64.
The tests copyright headers will likely need to be updated (2025) since
the patch dated from December last year.
You can keep the RB if you update the copyright year, LGTM.
Reviewed-by: Frédéric Bérat <fberat@redhat.com>
> ---
> ctype/Makefile | 17 ++++++++
> ctype/ctype-info.c | 14 ++++--
> ctype/tst-ctype-tls-dlmopen.c | 2 +
> ctype/tst-ctype-tls-dlopen-static.c | 2 +
> ctype/tst-ctype-tls-mod.c | 37 ++++++++++++++++
> ctype/tst-ctype-tls-skeleton.c | 67 +++++++++++++++++++++++++++++
> 6 files changed, 136 insertions(+), 3 deletions(-)
> create mode 100644 ctype/tst-ctype-tls-dlmopen.c
> create mode 100644 ctype/tst-ctype-tls-dlopen-static.c
> create mode 100644 ctype/tst-ctype-tls-mod.c
> create mode 100644 ctype/tst-ctype-tls-skeleton.c
>
> diff --git a/ctype/Makefile b/ctype/Makefile
> index 3e09938bd1..b7cd5f2282 100644
> --- a/ctype/Makefile
> +++ b/ctype/Makefile
> @@ -36,6 +36,23 @@ aux := ctype-info
>
> tests := \
> test_ctype \
> + tst-ctype-tls-dlmopen \
> + tst-ctype-tls-dlopen-static \
> # tests
>
> +tests-static := \
> + tst-ctype-tls-dlopen-static \
> + # tests-static
> +
> +modules-names := \
> + tst-ctype-tls-mod \
> + # modules-names
> +
> include ../Rules
> +
> +$(objpfx)tst-ctype-tls-dlmopen: $(shared-thread-library)
> +$(objpfx)tst-ctype-tls-dlmopen.out: $(objpfx)tst-ctype-tls-mod.so
> +$(objpfx)tst-ctype-tls-dlopen-static: $(static-thread-library)
> +$(objpfx)tst-ctype-tls-dlopen-static.out: $(objpfx)tst-ctype-tls-mod.so
> +tst-ctype-tls-dlopen-static-ENV = \
> + LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx):$(common-objpfx)elf
> diff --git a/ctype/ctype-info.c b/ctype/ctype-info.c
> index 94e312d91f..621bd4239c 100644
> --- a/ctype/ctype-info.c
> +++ b/ctype/ctype-info.c
> @@ -19,9 +19,17 @@
> #include <ctype.h>
> #include <locale/localeinfo.h>
>
> -__thread const uint16_t * __libc_tsd_CTYPE_B;
> -__thread const int32_t * __libc_tsd_CTYPE_TOLOWER;
> -__thread const int32_t * __libc_tsd_CTYPE_TOUPPER;
> +/* Fallback initialization using relocations. See the _nl_C_locobj
> + initializers in locale/xlocale.c. Usually, this is overwritten by
> + __ctype_init before user code runs, but this does not happen for
> + threads in secondary namespaces. With the initializers, secondary
> + namespaces at least get locale data from the C locale. */
> +__thread const uint16_t * __libc_tsd_CTYPE_B
> + = (const uint16_t *) _nl_C_LC_CTYPE_class + 128;
> +__thread const int32_t * __libc_tsd_CTYPE_TOLOWER
> + = (const int32_t *) _nl_C_LC_CTYPE_tolower + 128;
> +__thread const int32_t * __libc_tsd_CTYPE_TOUPPER
> + = (const int32_t *) _nl_C_LC_CTYPE_toupper + 128;
>
>
> void
> diff --git a/ctype/tst-ctype-tls-dlmopen.c b/ctype/tst-ctype-tls-dlmopen.c
> new file mode 100644
> index 0000000000..f7eeb65551
> --- /dev/null
> +++ b/ctype/tst-ctype-tls-dlmopen.c
> @@ -0,0 +1,2 @@
> +#define DO_STATIC_TEST 0
> +#include "tst-ctype-tls-skeleton.c"
> diff --git a/ctype/tst-ctype-tls-dlopen-static.c b/ctype/tst-ctype-tls-dlopen-static.c
> new file mode 100644
> index 0000000000..c2c09c362c
> --- /dev/null
> +++ b/ctype/tst-ctype-tls-dlopen-static.c
> @@ -0,0 +1,2 @@
> +#define DO_STATIC_TEST 1
> +#include "tst-ctype-tls-skeleton.c"
> diff --git a/ctype/tst-ctype-tls-mod.c b/ctype/tst-ctype-tls-mod.c
> new file mode 100644
> index 0000000000..dba689701f
> --- /dev/null
> +++ b/ctype/tst-ctype-tls-mod.c
> @@ -0,0 +1,37 @@
> +/* Wrappers for <ctype.h> macros in a secondary namespace.
> + Copyright (C) 2024 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <ctype.h>
> +
> +int
> +my_isalpha (int ch)
> +{
> + return isalpha (ch);
> +}
> +
> +int
> +my_toupper (int ch)
> +{
> + return toupper (ch);
> +}
> +
> +int
> +my_tolower (int ch)
> +{
> + return tolower (ch);
> +}
> diff --git a/ctype/tst-ctype-tls-skeleton.c b/ctype/tst-ctype-tls-skeleton.c
> new file mode 100644
> index 0000000000..421c984f70
> --- /dev/null
> +++ b/ctype/tst-ctype-tls-skeleton.c
> @@ -0,0 +1,67 @@
> +/* Test that <ctype.h> in a secondary namespace works.
> + Copyright (C) 2024 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +/* Before this file is included, define DO_STATIC_TEST to 0 or 1.
> + With 0, dlmopen is used for the test. With 1, dlopen is used. */
> +
> +#include <stddef.h>
> +#include <stdlib.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/xdlfcn.h>
> +#include <support/xthread.h>
> +
> +static int (*my_isalpha) (int);
> +static int (*my_toupper) (int);
> +static int (*my_tolower) (int);
> +
> +static void *
> +checks (void *ignore)
> +{
> + TEST_VERIFY (my_isalpha ('a'));
> + TEST_VERIFY (!my_isalpha ('0'));
> + TEST_COMPARE (my_toupper ('a'), 'A');
> + TEST_COMPARE (my_toupper ('A'), 'A');
> + TEST_COMPARE (my_tolower ('a'), 'a');
> + TEST_COMPARE (my_tolower ('A'), 'a');
> + return NULL;
> +}
> +
> +static int
> +do_test (void)
> +{
> + char *dso = xasprintf ("%s/ctype/tst-ctype-tls-mod.so", support_objdir_root);
> +#if DO_STATIC_TEST
> + void *handle = xdlopen (dso, RTLD_LAZY);
> +#else
> + void *handle = xdlmopen (LM_ID_NEWLM, dso, RTLD_LAZY);
> +#endif
> + my_isalpha = xdlsym (handle, "my_isalpha");
> + my_toupper = xdlsym (handle, "my_toupper");
> + my_tolower = xdlsym (handle, "my_tolower");
> +
> + checks (NULL);
> + xpthread_join (xpthread_create (NULL, checks, NULL));
> +
> + xdlclose (handle);
> + free (dso);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
More information about the Libc-alpha
mailing list