[PATCH v4] libio: Fix ungetwc operating on byte stream [BZ #33998]
Florian Weimer
fweimer@redhat.com
Thu Apr 30 16:11:16 GMT 2026
* Rocket Ma:
> diff --git a/libio/bug-wgenops-bz33998.c b/libio/bug-wgenops-bz33998.c
> new file mode 100644
> index 0000000000..b3f750a753
> --- /dev/null
> +++ b/libio/bug-wgenops-bz33998.c
> @@ -0,0 +1,44 @@
> +/* Regression test for ungetwc operating on byte stream (BZ #33998)
> + Copyright (C) 2026 The GNU Toolchain Authors.
> + 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 <unistd.h>
> +#include <sys/mman.h>
> +#include <stdio.h>
> +#include <wchar.h>
> +#include <support/check.h>
> +
> +static int
> +do_test (void)
> +{
> + int fd = memfd_create ("test", MFD_CLOEXEC);
> + TEST_VERIFY (fd != -1);
This may fail on older kernels, so please use create_temp_file from
<support/temp_file.h>.
> + TEST_COMPARE (write (fd, (unsigned char[]){ 'A', 0, 0, 0 }, 4), 4);
> + TEST_COMPARE (lseek (fd, 0, SEEK_SET), 0);
> + FILE *fp = fdopen (fd, "r+");
You could use xwrite, xlseek, xfopen.
> + TEST_VERIFY (fp != NULL);
> + TEST_COMPARE (getwc (fp), L'A');
> +
> + /* if the bug is fixed, then ungetwc should not touch byte stream. */
> + char *old_read_ptr = fp->_IO_read_ptr;
> + TEST_COMPARE (ungetwc (0, fp), L'\0');
Can you please use 0 or L'\0' in both places?
> + TEST_VERIFY (fp->_IO_read_ptr == old_read_ptr);
You could check that the null character can be read back with fgetwc.
And call xfclose at the end.
> diff --git a/libio/wgenops.c b/libio/wgenops.c
> index 6829477e0c..5f36bc49a1 100644
> --- a/libio/wgenops.c
> +++ b/libio/wgenops.c
> @@ -110,8 +110,8 @@ _IO_wdefault_pbackfail (FILE *fp, wint_t c)
> {
> if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
> && !_IO_in_backup (fp)
> - && (wint_t) fp->_IO_read_ptr[-1] == c)
> - --fp->_IO_read_ptr;
> + && (wint_t) fp->_wide_data->_IO_read_ptr[-1] == c)
> + --fp->_wide_data->_IO_read_ptr;
> else
> {
> /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
The fix itself looks good to me.
Thanks,
Florian
More information about the Libc-alpha
mailing list