From: Collin Funk Date: Fri, 10 Oct 2025 03:41:09 +0000 (-0700) Subject: getline: Work around a glibc bug. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ac88aebea47cbc46c263a064dbd569e72ccba8b;p=thirdparty%2Fgnulib.git 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. --- diff --git a/ChangeLog b/ChangeLog index 7e14807d12..f3c4a487d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2025-10-10 Collin Funk + 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. diff --git a/doc/posix-functions/getline.texi b/doc/posix-functions/getline.texi index 6edc3a56ef..cfef3c8867 100644 --- a/doc/posix-functions/getline.texi +++ b/doc/posix-functions/getline.texi @@ -22,6 +22,11 @@ signature, for example in -linet. This function crashes when passed a pointer to a NULL buffer together with a pointer to a non-zero buffer size on some platforms: FreeBSD 8.0. +@item +This function does not NUL terminate the buffer when the first +character read is EOF on some platforms: +@c https://sourceware.org/PR28038 +glibc 2.42. @end itemize Portability problems not fixed by Gnulib: diff --git a/m4/getline.m4 b/m4/getline.m4 index b97b801124..14f84c53ce 100644 --- a/m4/getline.m4 +++ b/m4/getline.m4 @@ -1,5 +1,5 @@ # getline.m4 -# serial 33 +# serial 34 dnl Copyright (C) 1998-2003, 2005-2007, 2009-2025 Free Software Foundation, dnl Inc. @@ -31,6 +31,7 @@ AC_DEFUN([gl_FUNC_GETLINE], 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 # include @@ -38,6 +39,7 @@ AC_DEFUN([gl_FUNC_GETLINE], int main () { FILE *in = fopen ("./conftest.data", "r"); + int result = 0; if (!in) return 1; { @@ -47,7 +49,7 @@ AC_DEFUN([gl_FUNC_GETLINE], 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); } { @@ -56,34 +58,39 @@ AC_DEFUN([gl_FUNC_GETLINE], 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 -#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