forked from rpms/glibc
Add more tests of getline (RHEL-54413)
Resolves: RHEL-54413
This commit is contained in:
parent
9d46c1dd61
commit
a2d1e68858
630
glibc-RHEL-54413.patch
Normal file
630
glibc-RHEL-54413.patch
Normal file
@ -0,0 +1,630 @@
|
||||
commit 7f04bb4e49413bd57ac3215f3480b09ae7131968
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Wed Aug 21 19:58:14 2024 +0000
|
||||
|
||||
Add more tests of getline
|
||||
|
||||
There is very little test coverage for getline (only a minimal
|
||||
stdio-common/tstgetln.c which doesn't verify anything about the
|
||||
results of the getline calls). Add some more thorough tests
|
||||
(generally using fopencookie for convenience in testing various cases
|
||||
for what the input and possible errors / EOF in the file read might
|
||||
look like).
|
||||
|
||||
Note the following regarding testing of error cases:
|
||||
|
||||
* Nothing is said in the specifications about what if anything might
|
||||
be written into the buffer, and whether it might be reallocated, in
|
||||
error cases. The expectation of the tests (required to avoid memory
|
||||
leaks on error) is that at least on error cases, the invariant that
|
||||
lineptr points to at least n bytes is maintained.
|
||||
|
||||
* The optional EOVERFLOW error case specified in POSIX, "The number of
|
||||
bytes to be written into the buffer, including the delimiter
|
||||
character (if encountered), would exceed {SSIZE_MAX}.", doesn't seem
|
||||
practically testable, as any case reading so many characters (half
|
||||
the address space) would also be liable to run into allocation
|
||||
failure along (ENOMEM) the way.
|
||||
|
||||
* If a read error occurs part way through reading an input line, it
|
||||
seems unclear whether a partial line should be returned by getline
|
||||
(avoid input getting lost), which is what glibc does at least in the
|
||||
fopencookie case used in this test, or whether getline should return
|
||||
-1 (error) (so avoiding the program misbehaving by processing a
|
||||
truncated line as if it were complete). (There was a short,
|
||||
inconclusive discussion about this on the Austin Group list on 9-10
|
||||
November 2014.)
|
||||
|
||||
* The POSIX specification of getline inherits errors from fgetc. I
|
||||
didn't try to cover fgetc errors systematically, just one example of
|
||||
such an error.
|
||||
|
||||
Tested for x86_64 and x86.
|
||||
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
|
||||
index bc314af0617e1647..ea8598bbe3a6dfdd 100644
|
||||
--- a/stdio-common/Makefile
|
||||
+++ b/stdio-common/Makefile
|
||||
@@ -177,6 +177,8 @@ tests := \
|
||||
tst-fread \
|
||||
tst-fseek \
|
||||
tst-fwrite \
|
||||
+ tst-getline \
|
||||
+ tst-getline-enomem \
|
||||
tst-gets \
|
||||
tst-grouping \
|
||||
tst-long-dbl-fphex \
|
||||
@@ -244,6 +246,8 @@ tests-special += \
|
||||
ifeq (yes,$(build-shared))
|
||||
ifneq ($(PERL),no)
|
||||
tests-special += \
|
||||
+ $(objpfx)tst-getline-enomem-mem.out \
|
||||
+ $(objpfx)tst-getline-mem.out \
|
||||
$(objpfx)tst-printf-bz18872-mem.out \
|
||||
$(objpfx)tst-printf-bz25691-mem.out \
|
||||
$(objpfx)tst-printf-fp-free-mem.out \
|
||||
@@ -252,6 +256,10 @@ tests-special += \
|
||||
# tests-special
|
||||
|
||||
generated += \
|
||||
+ tst-getline-enomem-mem.out \
|
||||
+ tst-getline-enomem.mtrace \
|
||||
+ tst-getline-mem.out \
|
||||
+ tst-getline.mtrace \
|
||||
tst-printf-bz18872-mem.out \
|
||||
tst-printf-bz18872.c \
|
||||
tst-printf-bz18872.mtrace \
|
||||
@@ -314,6 +322,12 @@ tst-scanf-bz27650-ENV = \
|
||||
tst-ungetc-leak-ENV = \
|
||||
MALLOC_TRACE=$(objpfx)tst-ungetc-leak.mtrace \
|
||||
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-getline-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-getline.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-getline-enomem-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-getline-enomem.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
|
||||
diff --git a/stdio-common/tst-getline-enomem.c b/stdio-common/tst-getline-enomem.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..7fc70ea9b51d1262
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-getline-enomem.c
|
||||
@@ -0,0 +1,78 @@
|
||||
+/* Test getline: ENOMEM on allocation failure.
|
||||
+ Copyright (C) 2024 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 <errno.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/resource.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/test-driver.h>
|
||||
+
|
||||
+/* Produce a stream of test data based on data in COOKIE (ignored),
|
||||
+ storing up to SIZE bytes in BUF. */
|
||||
+
|
||||
+static ssize_t
|
||||
+io_read (void *cookie, char *buf, size_t size)
|
||||
+{
|
||||
+ memset (buf, 'x', size);
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+/* Set up a test stream with fopencookie. */
|
||||
+
|
||||
+static FILE *
|
||||
+open_test_stream (void)
|
||||
+{
|
||||
+ static cookie_io_functions_t io_funcs = { .read = io_read };
|
||||
+ static int cookie;
|
||||
+ FILE *fp = fopencookie (&cookie, "r", io_funcs);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ return fp;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+ char *lineptr = NULL;
|
||||
+ size_t size = 0;
|
||||
+ ssize_t ret;
|
||||
+ mtrace ();
|
||||
+ /* Test ENOMEM (and error indicator for stream set) for memory
|
||||
+ allocation failure. */
|
||||
+ verbose_printf ("Testing memory allocation failure\n");
|
||||
+ fp = open_test_stream ();
|
||||
+ struct rlimit limit;
|
||||
+ TEST_VERIFY_EXIT (getrlimit (RLIMIT_AS, &limit) == 0);
|
||||
+ limit.rlim_cur = 32 * 1024 * 1024;
|
||||
+ TEST_VERIFY_EXIT (setrlimit (RLIMIT_AS, &limit) == 0);
|
||||
+ errno = 0;
|
||||
+ ret = getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, ENOMEM);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ free (lineptr);
|
||||
+ fclose (fp);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/stdio-common/tst-getline.c b/stdio-common/tst-getline.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..29eb7cec0f344872
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-getline.c
|
||||
@@ -0,0 +1,451 @@
|
||||
+/* Test getline.
|
||||
+ Copyright (C) 2024 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 <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <malloc.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+static struct test_data
|
||||
+{
|
||||
+ /* Input test data for fopencookie stream. */
|
||||
+ const char *in_data;
|
||||
+
|
||||
+ /* The amount of test data left. */
|
||||
+ size_t in_data_left;
|
||||
+
|
||||
+ /* Error number for forcing an error on next read. */
|
||||
+ int in_error;
|
||||
+
|
||||
+ /* Error number for forcing an error (rather than EOF) after all
|
||||
+ bytes read. */
|
||||
+ int in_error_after;
|
||||
+} the_cookie;
|
||||
+
|
||||
+/* Produce a stream of test data based on data in COOKIE, storing up
|
||||
+ to SIZE bytes in BUF. */
|
||||
+
|
||||
+static ssize_t
|
||||
+io_read (void *cookie, char *buf, size_t size)
|
||||
+{
|
||||
+ struct test_data *p = cookie;
|
||||
+ if (p->in_error)
|
||||
+ {
|
||||
+ errno = p->in_error;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (size > p->in_data_left)
|
||||
+ size = p->in_data_left;
|
||||
+ memcpy (buf, p->in_data, size);
|
||||
+ p->in_data += size;
|
||||
+ p->in_data_left -= size;
|
||||
+ if (p->in_data_left == 0)
|
||||
+ p->in_error = p->in_error_after;
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+/* Set up a test stream with fopencookie. */
|
||||
+
|
||||
+static FILE *
|
||||
+open_test_stream (const char *in_data, size_t size)
|
||||
+{
|
||||
+ static cookie_io_functions_t io_funcs = { .read = io_read };
|
||||
+ the_cookie.in_data = in_data;
|
||||
+ the_cookie.in_data_left = size;
|
||||
+ the_cookie.in_error = 0;
|
||||
+ the_cookie.in_error_after = 0;
|
||||
+ FILE *fp = fopencookie (&the_cookie, "r", io_funcs);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ return fp;
|
||||
+}
|
||||
+
|
||||
+/* Set up a test stream with fopencookie, using data from a string
|
||||
+ literal. */
|
||||
+#define OPEN_TEST_STREAM(IN_DATA) open_test_stream (IN_DATA, sizeof (IN_DATA))
|
||||
+
|
||||
+/* Wrap getline to verify that (as per the glibc manual), *LINEPTR is
|
||||
+ returned as non-null and with at least *N bytes (even on error or
|
||||
+ EOF). Also clear errno for the benefit of tests that check the
|
||||
+ value of errno after the call. */
|
||||
+
|
||||
+ssize_t
|
||||
+wrap_getline (char **lineptr, size_t *n, FILE *stream)
|
||||
+{
|
||||
+ errno = 0;
|
||||
+ ssize_t ret = getline (lineptr, n, stream);
|
||||
+ if (lineptr != NULL && n != NULL)
|
||||
+ {
|
||||
+ TEST_VERIFY (*lineptr != NULL);
|
||||
+ TEST_VERIFY (malloc_usable_size (*lineptr) >= *n);
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+ char *lineptr = NULL;
|
||||
+ size_t size = 0;
|
||||
+ ssize_t ret;
|
||||
+ mtrace ();
|
||||
+ /* Test failure with EINVAL (and error indicator for stream set) if
|
||||
+ lineptr is a null pointer. */
|
||||
+ verbose_printf ("Testing lineptr == NULL\n");
|
||||
+ fp = OPEN_TEST_STREAM ("test");
|
||||
+ ret = wrap_getline (NULL, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ fclose (fp);
|
||||
+ /* Test failure with EINVAL (and error indicator for stream set) if
|
||||
+ n is a null pointer. */
|
||||
+ verbose_printf ("Testing n == NULL\n");
|
||||
+ fp = OPEN_TEST_STREAM ("test");
|
||||
+ ret = wrap_getline (&lineptr, NULL, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ fclose (fp);
|
||||
+ /* Test failure with EINVAL (and error indicator for stream set) if
|
||||
+ both lineptr and n are null pointers. */
|
||||
+ verbose_printf ("Testing lineptr == NULL and n == NULL\n");
|
||||
+ fp = OPEN_TEST_STREAM ("test");
|
||||
+ ret = wrap_getline (NULL, NULL, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ fclose (fp);
|
||||
+ /* Test normal line, fitting in available space (including case with
|
||||
+ null bytes). */
|
||||
+ verbose_printf ("Testing normal nonempty input\n");
|
||||
+ lineptr = xmalloc (10);
|
||||
+ size = 10;
|
||||
+ fp = OPEN_TEST_STREAM ("foo\nbar\0\n\0baz\nte\0st\n");
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "foo\n", 5);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "bar\0\n", 6);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "\0baz\n", 6);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 6);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 7, "te\0st\n", 7);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 1);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 1, "", 1);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (ferror (fp), 0);
|
||||
+ TEST_COMPARE (!!feof (fp), 1);
|
||||
+ fclose (fp);
|
||||
+ /* Test normal line, with reallocation (including case with null bytes). */
|
||||
+ verbose_printf ("Testing normal nonempty input with reallocation\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = OPEN_TEST_STREAM ("foo\nbar\0\n\0baz\nte\0st\n"
|
||||
+ "foo\nbar\0\n\0baz\nte\0st\n");
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "foo\n", 5);
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "bar\0\n", 6);
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "\0baz\n", 6);
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 6);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 7, "te\0st\n", 7);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "foo\n", 5);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "bar\0\n", 6);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "\0baz\n", 6);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 6);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 7, "te\0st\n", 7);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 1);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 1, "", 1);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (ferror (fp), 0);
|
||||
+ TEST_COMPARE (!!feof (fp), 1);
|
||||
+ fclose (fp);
|
||||
+ /* Test EOF before delimiter but after some bytes read, fitting in
|
||||
+ available space (including case with null bytes). */
|
||||
+ verbose_printf ("Testing EOF before delimiter\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (10);
|
||||
+ size = 10;
|
||||
+ fp = open_test_stream ("foo", 3);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 3);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 4, "foo", 4);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (10);
|
||||
+ size = 10;
|
||||
+ fp = open_test_stream ("bar\0", 4);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "bar\0", 5);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (10);
|
||||
+ size = 10;
|
||||
+ fp = open_test_stream ("\0baz", 4);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "\0baz", 5);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (10);
|
||||
+ size = 10;
|
||||
+ fp = open_test_stream ("te\0st", 5);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "te\0st", 6);
|
||||
+ fclose (fp);
|
||||
+ /* Test EOF before delimiter but after some bytes read, with
|
||||
+ reallocation (including case with null bytes). */
|
||||
+ verbose_printf ("Testing EOF before delimiter with reallocation\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = open_test_stream ("foo", 3);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 3);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 4, "foo", 4);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = open_test_stream ("bar\0", 4);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "bar\0", 5);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = open_test_stream ("\0baz", 4);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "\0baz", 5);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = open_test_stream ("te\0st", 5);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "te\0st", 6);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ fp = open_test_stream ("foo", 3);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 3);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 4, "foo", 4);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ fp = open_test_stream ("bar\0", 4);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "bar\0", 5);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ fp = open_test_stream ("\0baz", 4);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 4);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 5, "\0baz", 5);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ fp = open_test_stream ("te\0st", 5);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 5);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 6, "te\0st", 6);
|
||||
+ fclose (fp);
|
||||
+ /* Test EOF with no bytes read (nothing is specified about anything
|
||||
+ written to the buffer), including EOF again when already at end
|
||||
+ of file. */
|
||||
+ verbose_printf ("Testing EOF with no bytes read\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = open_test_stream ("", 0);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (ferror (fp), 0);
|
||||
+ TEST_COMPARE (!!feof (fp), 1);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (ferror (fp), 0);
|
||||
+ TEST_COMPARE (!!feof (fp), 1);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ lineptr = xmalloc (1);
|
||||
+ size = 1;
|
||||
+ fp = open_test_stream ("", 0);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (ferror (fp), 0);
|
||||
+ TEST_COMPARE (!!feof (fp), 1);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (ferror (fp), 0);
|
||||
+ TEST_COMPARE (!!feof (fp), 1);
|
||||
+ fclose (fp);
|
||||
+ /* Test error occurring with no bytes read, including calling
|
||||
+ wrap_getline again while the file is in error state. */
|
||||
+ verbose_printf ("Testing error with no bytes read\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = open_test_stream ("", 0);
|
||||
+ the_cookie.in_error = EINVAL;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ /* Make sure error state is sticky. */
|
||||
+ the_cookie.in_error = 0;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ fclose (fp);
|
||||
+ /* Test error occurring after some bytes read. Specifications are
|
||||
+ ambiguous here; at least in the fopencookie case used for
|
||||
+ testing, glibc returns the partial line (but with the error
|
||||
+ indicator on the stream set). */
|
||||
+ verbose_printf ("Testing error after some bytes read\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = open_test_stream ("foo", 3);
|
||||
+ the_cookie.in_error_after = EINVAL;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, 3);
|
||||
+ TEST_COMPARE_BLOB (lineptr, 4, "foo", 4);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ /* Make sure error state is sticky. */
|
||||
+ the_cookie.in_error = 0;
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ fclose (fp);
|
||||
+ /* Test EBADF error as a representative example of an fgetc error
|
||||
+ resulting in an error from wrap_getline. We don't try to cover all
|
||||
+ error cases for fgetc here. */
|
||||
+ verbose_printf ("Testing EBADF error\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ fp = xfopen ("/dev/null", "r");
|
||||
+ xclose (fileno (fp));
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, EBADF);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ fclose (fp);
|
||||
+ /* Test EAGAIN error as an example of an fgetc error on a valid file
|
||||
+ descriptor. */
|
||||
+ verbose_printf ("Testing EAGAIN error\n");
|
||||
+ free (lineptr);
|
||||
+ lineptr = NULL;
|
||||
+ size = 0;
|
||||
+ int pipefd[2];
|
||||
+ xpipe (pipefd);
|
||||
+ ret = fcntl (pipefd[0], F_SETFL, O_NONBLOCK);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ fp = fdopen (pipefd[0], "r");
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, EAGAIN);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ /* Make sure error state is sticky (even after more data is
|
||||
+ available to read). */
|
||||
+ xwrite (pipefd[1], "x\n", 2);
|
||||
+ ret = wrap_getline (&lineptr, &size, fp);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (!!ferror (fp), 1);
|
||||
+ TEST_COMPARE (feof (fp), 0);
|
||||
+ fclose (fp);
|
||||
+ free (lineptr);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -157,7 +157,7 @@ end \
|
||||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: 138%{?dist}
|
||||
Release: 139%{?dist}
|
||||
|
||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||
# libraries.
|
||||
@ -916,6 +916,7 @@ Patch677: glibc-RHEL-66253-3.patch
|
||||
Patch678: glibc-RHEL-46733-1.patch
|
||||
Patch679: glibc-RHEL-46733-2.patch
|
||||
Patch680: glibc-RHEL-46733-3.patch
|
||||
Patch681: glibc-RHEL-54413.patch
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -3075,6 +3076,9 @@ update_gconv_modules_cache ()
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Nov 7 2024 Florian Weimer <fweimer@redhat.com> - 2.34-139
|
||||
- Add more tests of getline (RHEL-54413)
|
||||
|
||||
* Thu Nov 7 2024 Florian Weimer <fweimer@redhat.com> - 2.34-138
|
||||
- Add fclose testcases (RHEL-46733)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user