[PATCH] test: Fix and stabilize tst-wcsmbs-clone-overflow test
Frederic Berat
fberat@redhat.com
Tue May 26 16:20:28 GMT 2026
On Tue, May 26, 2026 at 2:54 PM Adhemerval Zanella Netto <
adhemerval.zanella@linaro.org> wrote:
>
>
> On 26/05/26 08:45, Frédéric Bérat wrote:
> > The test tst-wcsmbs-clone-overflow was initially added to tests-static.
> > However, this causes the test to be unstable because gconv modules
> > dynamically load libc.so. Any discrepancy between the statically linked
> > version and the dynamically loaded one can lead to a crash.
>
> It is not clear when this would happen, is it the case that the tests
> is loading the system gconv modules instead of the one in the build
> directory?
>
If my understanding of the strace is correct, gconv dlopen the system's
libc during its execution, leading to potential mismatch between the
statically linked libc and the dlopen'ed one.
That's also the only explanation I could find for the SIGFPE raised on
linaro boxes on arm: GDB traces show the SIGFPE being raised during the
dlopen operation.
Note that while I could reproduce the SIGFPE until Tuesday last week, I
couldn't on Wednesday. I therefore assumed that the Linaro image got
updated with a Glibc version close enough to the one I tested that it no
longer triggered the SIGFPE.
>
> >
> > By removing the test from tests-static, it relies on dynamic linking,
> > safely bypassing the dlopen crash. Since the test is now dynamically
> > linked, it cannot use the internal thread-local symbol
> > _NL_CURRENT_DATA(LC_CTYPE) because _nl_current_LC_CTYPE is hidden in
> > libc.so, leading to undefined references. Thus, the test now uses
> > newlocale and uselocale, safely extracting the locale data from the
> > returned locale_t object.
> >
> > Furthermore, using newlocale requires the gconv-modules configuration to
> > be built and available so that the ISO8859-1.so module can be
> > dynamically loaded. Otherwise, glibc falls back to the built-in C locale
> > conversions, leaving __shlib_handle as NULL and silently bypassing the
> > reference counter increment.
> > A new Makefile fragment, gen-gconv-modules.mk, is introduced to ensure
> > the gconv-modules are built before the test runs, and an explicit check
> > for __shlib_handle != NULL is added to the test.
> > ---
> > gen-gconv-modules.mk | 6 ++++++
> > localedata/Makefile | 6 ++----
> > wcsmbs/Makefile | 7 ++-----
> > wcsmbs/tst-wcsmbs-clone-overflow.c | 12 +++++++++---
> > 4 files changed, 19 insertions(+), 12 deletions(-)
> > create mode 100644 gen-gconv-modules.mk
> >
> > diff --git a/gen-gconv-modules.mk b/gen-gconv-modules.mk
> > new file mode 100644
> > index 0000000000..046721a7a7
> > --- /dev/null
> > +++ b/gen-gconv-modules.mk
> > @@ -0,0 +1,6 @@
> > +# defines target $(gen-gconv-modules) that ensures gconv-modules are
> available
> > +
> > +gen-gconv-modules := $(common-objpfx)iconvdata/gconv-modules
> > +
> > +$(gen-gconv-modules):
> > + $(MAKE) -C ../iconvdata subdir=iconvdata $@
> > diff --git a/localedata/Makefile b/localedata/Makefile
> > index 6c9fe7c5c4..0fb1d78c29 100644
> > --- a/localedata/Makefile
> > +++ b/localedata/Makefile
> > @@ -287,7 +287,7 @@ install-others := $(addprefix $(inst_i18ndir)/, \
> > $(locales))
> > endif
> >
> > -tests: $(objdir)/iconvdata/gconv-modules
> > +tests: $(gen-gconv-modules)
> >
> > tests-static += \
> > tst-langinfo-newlocale-static \
> > @@ -412,6 +412,7 @@ LOCALES := \
> > # LOCALES
> >
> > include ../gen-locales.mk
> > +include ../gen-gconv-modules.mk
> >
> > $(objpfx)tst-iconv-emojis-trans.out: $(gen-locales)
> >
> > @@ -587,6 +588,3 @@ $(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
> >
> > bug-setlocale1-ENV-only = LOCPATH=$(objpfx) LC_CTYPE=de_DE.UTF-8
> > bug-setlocale1-static-ENV-only = $(bug-setlocale1-ENV-only)
> > -
> > -$(objdir)/iconvdata/gconv-modules:
> > - $(MAKE) -C ../iconvdata subdir=iconvdata $@
> > diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
> > index ee3638c0e5..f4f89c030f 100644
> > --- a/wcsmbs/Makefile
> > +++ b/wcsmbs/Makefile
> > @@ -213,10 +213,6 @@ xtests += test-wcsncmp-nonarray
> > tests-internal += \
> > tst-wcsmbs-clone-overflow
> >
> > -tests-static += \
> > - tst-wcsmbs-clone-overflow
> > -
> > -
> > include ../Rules
> >
> > ifeq ($(run-built-tests),yes)
> > @@ -233,6 +229,7 @@ LOCALES := \
> > zh_TW.EUC-TW \
> > # LOCALES
> > include ../gen-locales.mk
> > +include ../gen-gconv-modules.mk
> >
> > $(objpfx)tst-btowc.out: $(gen-locales)
> > $(objpfx)tst-c16c32-1.out: $(gen-locales)
> > @@ -247,7 +244,7 @@ $(objpfx)tst-c32-state.out: $(gen-locales)
> > $(objpfx)test-c8rtomb.out: $(gen-locales)
> > $(objpfx)test-mbrtoc8.out: $(gen-locales)
> > $(objpfx)tst-wscanf-to_inpunct.out: $(gen-locales)
> > -$(objpfx)tst-wcsmbs-clone-overflow.out: $(gen-locales)
> > +$(objpfx)tst-wcsmbs-clone-overflow.out: $(gen-locales)
> $(gen-gconv-modules)
> > endif
> >
> > $(objpfx)tst-wcstod-round: $(libm)
> > diff --git a/wcsmbs/tst-wcsmbs-clone-overflow.c
> b/wcsmbs/tst-wcsmbs-clone-overflow.c
> > index adfd4fa61d..99461ea087 100644
> > --- a/wcsmbs/tst-wcsmbs-clone-overflow.c
> > +++ b/wcsmbs/tst-wcsmbs-clone-overflow.c
> > @@ -30,8 +30,11 @@
> > static int
> > do_test (void)
> > {
> > - if (setlocale (LC_ALL, "de_DE.ISO-8859-1") == NULL)
> > - FAIL_EXIT1 ("setlocale failed, check if de_DE.ISO-8859-1 is
> generated");
> > + locale_t loc_obj = newlocale (LC_ALL_MASK, "de_DE.ISO-8859-1", NULL);
> > + if (loc_obj == NULL)
> > + FAIL_EXIT1 ("newlocale failed, check if de_DE.ISO-8859-1 is
> generated");
> > +
> > + uselocale (loc_obj);
> >
> > wchar_t buf[32] = L"123";
> > int j;
> > @@ -41,7 +44,7 @@ do_test (void)
> > FAIL_EXIT1 ("swscanf failed");
> >
> > /* Retrieve the current gconv_fcts from the LC_CTYPE locale data. */
> > - struct __locale_data *loc = _NL_CURRENT_DATA (LC_CTYPE);
> > + struct __locale_data *loc = loc_obj->__locales[LC_CTYPE];
> > struct lc_ctype_data *ctype = loc->private;
> > const struct gconv_fcts *fcts = ctype->fcts;
> >
> > @@ -51,6 +54,9 @@ do_test (void)
> > /* Capture the reference counter. */
> > int initial_counter = fcts->towc->__counter;
> >
> > + if (fcts->towc->__shlib_handle == NULL)
> > + FAIL_EXIT1 ("__shlib_handle is NULL!");
> > +
> > /* Perform a second iteration of swscanf. If the stack-allocated FILE
> > leaks the gconv reference, the counter will increment. */
> > if (swscanf (buf, L"%d", &j) < 1)
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260526/24140cd9/attachment-0001.htm>
More information about the Libc-alpha
mailing list