[PATCH v2] libio: Fix fread stream orientation [BZ #22796]

Sam Zeter samuelzeter@gmail.com
Tue May 20 06:33:44 GMT 2025


Just following up on this as I haven't had any feedback yet.

On Thu, 3 Apr 2025 at 17:49, Samuel Zeter <samuelzeter@gmail.com> wrote:
>
> When using fread, stream orientation is only set in the case when
> less than a buffer's worth (4096 bytes) of data is requested. In this
> case the __underflow function is called, and the orientation set.
>
> In the case where more than 4096 bytes are needed, the __underflow function
> is skipped, and hence the stream's orientation is left unset.
>
> Setting the orientation to byte oriented before any buffer filling logic
> ensures that the orientation is set correctly regardless of the amount of
> data requested.
> --- This update moves the stream setting to the external interface
>  libio/Makefile      |   1 +
>  libio/iofread.c     |   5 +++
>  libio/tst-bz22796.c | 101 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 107 insertions(+)
>  create mode 100644 libio/tst-bz22796.c
>
> diff --git a/libio/Makefile b/libio/Makefile
> index e143ccdb2c..7db9f73f7b 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -91,6 +91,7 @@ tests = \
>    tst-asprintf-null \
>    tst-atime \
>    tst-bz22415 \
> +  tst-bz22796 \
>    tst-bz24051 \
>    tst-bz24153 \
>    tst-bz28828 \
> diff --git a/libio/iofread.c b/libio/iofread.c
> index 46f196de63..59fe064eba 100644
> --- a/libio/iofread.c
> +++ b/libio/iofread.c
> @@ -35,6 +35,11 @@ _IO_fread (void *buf, size_t size, size_t count, FILE *fp)
>    if (bytes_requested == 0)
>      return 0;
>    _IO_acquire_lock (fp);
> +
> +  /* Set the stream to byte oriented */
> +  if (fp->_mode == 0)
> +    _IO_fwide (fp, -1);
> +
>    bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested);
>    _IO_release_lock (fp);
>    return bytes_requested == bytes_read ? count : bytes_read / size;
> diff --git a/libio/tst-bz22796.c b/libio/tst-bz22796.c
> new file mode 100644
> index 0000000000..69d2a7f1b7
> --- /dev/null
> +++ b/libio/tst-bz22796.c
> @@ -0,0 +1,101 @@
> +/* Test to ensure stream orientation is set when reading large
> +   buffer sizes with fread (BZ#22796).
> +
> +   Copyright (C) 2019-2025 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 <stdio.h>
> +#include <stdlib.h>
> +#include <wchar.h>
> +
> +#include <support/check.h>
> +#include <support/temp_file.h>
> +
> +static int fd;
> +static FILE *fp = NULL;
> +static char buffer[BUFSIZ] = { 0 };
> +
> +static void
> +setup (void)
> +{
> +  int ret;
> +
> +  fd = create_temp_file ("bz22796", NULL);
> +  if (fd == -1)
> +      FAIL_EXIT1 ("create_temp_file failed");
> +
> +  fp = fdopen (fd, "w");
> +  if (fp == NULL)
> +      FAIL_EXIT1 ("fopen for file bz22796 returned NULL.");
> +
> +  /* The stream should have no orientation set yet */
> +  ret = fwide (fp, 0);
> +  if (ret != 0)
> +      FAIL_EXIT1 (
> +          "Error: Orientation already set. fwide returned %d.\n", ret);
> +}
> +
> +static int
> +test_read_large_buffer (void)
> +{
> +  int ret;
> +
> +  setup ();
> +
> +  /* Read a large amount of bytes */
> +  fread (buffer, 4, BUFSIZ / 4, fp);
> +
> +  /* Stream should now be byte orientated */
> +  ret = fwide (fp, 0);
> +  if (ret != -1)
> +      FAIL_RET ("fread returned %d, expected -1.\n", ret);
> +
> +  return 0;
> +}
> +
> +static int
> +test_read_small_buffer (void)
> +{
> +  int ret;
> +
> +  setup ();
> +
> +  /* Read a small amount of bytes */
> +  fread (buffer, 4, 4, fp);
> +
> +  /* Stream should now be byte orientated */
> +  ret = fwide (fp, 0);
> +  if (ret != -1)
> +      FAIL_RET ("fread returned %d, expected -1.\n", ret);
> +
> +  return 0;
> +}
> +
> +static int
> +do_test (void)
> +{
> +  int ret = 0;
> +
> +  ret = test_read_small_buffer ();
> +  ret += test_read_large_buffer ();
> +
> +  fclose (fp);
> +
> +  return ret;
> +}
> +
> +#include <support/test-driver.c>
> --
> 2.49.0
>


More information about the Libc-alpha mailing list