[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