mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
7f04bb4e49
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.
79 lines
2.2 KiB
C
79 lines
2.2 KiB
C
/* 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>
|