2025-10-10 Collin Funk <collin.funk1@gmail.com>
+ getline: Work around a glibc bug.
+ * m4/getline.m4 (gl_FUNC_GETLINE): Check that the buffer is terminated
+ with a NUL character when the first character read is EOF. Guess that
+ the function does not work on glibc.
+ * doc/posix-functions/getline.texi: Mention the bug.
+
getdelim tests: Add a test for the glibc bug.
* tests/test-getdelim.c (main): Check that the buffer is terminated with
a NUL character when the first character read is EOF.
# getline.m4
-# serial 33
+# serial 34
dnl Copyright (C) 1998-2003, 2005-2007, 2009-2025 Free Software Foundation,
dnl Inc.
AC_CACHE_CHECK([for working getline function],
[am_cv_func_working_getline],
[echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data
+ touch conftest.empty
AC_RUN_IFELSE([AC_LANG_SOURCE([[
# include <stdio.h>
# include <stdlib.h>
int main ()
{
FILE *in = fopen ("./conftest.data", "r");
+ int result = 0;
if (!in)
return 1;
{
size_t siz = 0;
int len = getline (&line, &siz, in);
if (!(len == 4 && line && strcmp (line, "foo\n") == 0))
- { free (line); fclose (in); return 2; }
+ result |= 2;
free (line);
}
{
char *line = NULL;
size_t siz = (size_t)(~0) / 4;
if (getline (&line, &siz, in) == -1)
- { fclose (in); return 3; }
+ result |= 4;
free (line);
}
fclose (in);
- return 0;
+ {
+ /* Test that reading EOF as the first character sets the first byte
+ in the buffer to NUL. This fails on glibc 2.42 and earlier. */
+ in = fopen ("./conftest.empty", "r");
+ if (!in)
+ return 1;
+ char *line = malloc (1);
+ line[0] = 'A';
+ size_t siz = 1;
+ if (getline (&line, &siz, in) != -1 || line[0] != '\0')
+ result |= 8;
+ free (line);
+ }
+ fclose (in);
+ return result;
}
]])],
[am_cv_func_working_getline=yes],
[am_cv_func_working_getline=no],
- [dnl We're cross compiling.
- dnl Guess it works on glibc2 systems and musl systems.
- AC_EGREP_CPP([Lucky GNU user],
- [
-#include <features.h>
-#ifdef __GNU_LIBRARY__
- #if (__GLIBC__ >= 2) && !defined __UCLIBC__
- Lucky GNU user
- #endif
-#endif
- ],
- [am_cv_func_working_getline="guessing yes"],
- [case "$host_os" in
- *-musl* | midipix*) am_cv_func_working_getline="guessing yes" ;;
- *) am_cv_func_working_getline="$gl_cross_guess_normal" ;;
- esac
- ])
+ [case "$host_os" in
+ # Guess yes on musl.
+ *-musl* | midipix*) am_cv_func_working_getline="guessing yes" ;;
+ # Guess no on glibc.
+ *-gnu* | gnu*) am_cv_func_working_getline="guessing no" ;;
+ *) am_cv_func_working_getline="$gl_cross_guess_normal" ;;
+ esac
])
- ])
+ rm -f conftest.data conftest.empty
+ ])
else
am_cv_func_working_getline=no
case "$gl_cv_onwards_func_getline" in