]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
getline: Work around a glibc bug.
authorCollin Funk <collin.funk1@gmail.com>
Fri, 10 Oct 2025 03:41:09 +0000 (20:41 -0700)
committerCollin Funk <collin.funk1@gmail.com>
Sat, 11 Oct 2025 00:37:27 +0000 (17:37 -0700)
* 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.

ChangeLog
doc/posix-functions/getline.texi
m4/getline.m4

index 7e14807d1272a584043b50e5554b3b68b09d29ea..f3c4a487d88176b0fad9955e46a7e283f26fc4ee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 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.
index 6edc3a56efa8c26a5b09c40b7dfdf7d94a568463..cfef3c88674dfa903e0a03528ec44c17d6b992bc 100644 (file)
@@ -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:
index b97b801124828da1097c21d35b44223419b98fe6..14f84c53ce71d8eab1a42f0e17442e8b2885fe8b 100644 (file)
@@ -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 <stdio.h>
 #    include <stdlib.h>
@@ -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 <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