[PATCH v1 2/2] test: Add gconv refcount leak test for swscanf
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Thu May 7 13:34:27 GMT 2026
On 07/05/26 05:11, Frédéric Bérat wrote:
> Add a new internal test, `tst-wcsmbs-clone-overflow`, to verify correct
> gconv module reference counting. The Makefile is updated to include this
> test in the `tests-internal` list and ensure it runs with generated locales.
>
> This test specifically checks that the `__counter` for `gconv_fcts->towc`
> does not leak references when `swscanf` is used with a stack-allocated
> wide character stream. It ensures that `_IO_wstrfile_fclose_stack`
> properly decrements the module reference counter, preventing a module
> from staying loaded indefinitely due to unreleased references.
>
> Assisted-by: LLM
LGTM, thanks.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
> Changes since v0:
> - Reworked the test to be an interna; test that directly checks the
> counter value.
>
> wcsmbs/Makefile | 7 ++++
> wcsmbs/tst-wcsmbs-clone-overflow.c | 66 ++++++++++++++++++++++++++++++
> 2 files changed, 73 insertions(+)
> create mode 100644 wcsmbs/tst-wcsmbs-clone-overflow.c
>
> diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
> index 849a47971e..ee3638c0e5 100644
> --- a/wcsmbs/Makefile
> +++ b/wcsmbs/Makefile
> @@ -210,6 +210,12 @@ tests := \
> # This test runs for a long time.
> xtests += test-wcsncmp-nonarray
>
> +tests-internal += \
> + tst-wcsmbs-clone-overflow
> +
> +tests-static += \
> + tst-wcsmbs-clone-overflow
> +
>
> include ../Rules
>
> @@ -241,6 +247,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)
> endif
>
> $(objpfx)tst-wcstod-round: $(libm)
> diff --git a/wcsmbs/tst-wcsmbs-clone-overflow.c b/wcsmbs/tst-wcsmbs-clone-overflow.c
> new file mode 100644
> index 0000000000..adfd4fa61d
> --- /dev/null
> +++ b/wcsmbs/tst-wcsmbs-clone-overflow.c
> @@ -0,0 +1,66 @@
> +/* Test for gconv module reference counter leak.
> + Copyright (C) 2026 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 <locale.h>
> +#include <stdio.h>
> +#include <wchar.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +
> +/* Internal headers for accessing the gconv structures. */
> +#include <locale/localeinfo.h>
> +#include <iconv/gconv_int.h>
> +#include <wcsmbs/wcsmbsload.h>
> +
> +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");
> +
> + wchar_t buf[32] = L"123";
> + int j;
> +
> + /* First iteration initializes the gconv functions internally. */
> + if (swscanf (buf, L"%d", &j) < 1)
> + 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 lc_ctype_data *ctype = loc->private;
> + const struct gconv_fcts *fcts = ctype->fcts;
> +
> + TEST_VERIFY_EXIT (fcts != NULL);
> + TEST_VERIFY_EXIT (fcts->towc != NULL);
> +
> + /* Capture the reference counter. */
> + int initial_counter = fcts->towc->__counter;
> +
> + /* 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)
> + FAIL_EXIT1 ("swscanf failed");
> +
> + /* The counter should be unchanged, as _IO_wstrfile_fclose_stack should
> + have decremented it correctly. */
> + TEST_COMPARE (fcts->towc->__counter, initial_counter);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
More information about the Libc-alpha
mailing list