Bruno Haible <[email protected]> writes:

> I disagree with the direction of this patch. Your previous commits from
> 2025-10-10 were based on the assumption that glibc 2.42 has a bug.
> But now that POSIX has relaxed the requirements [4], it's not a bug any
> more: all three behaviours are POSIX compliant. It's merely a portability
> problem.
>
> Since, additionally, this portability problem is not frequently encountered,
> and glibc 2.43 fixes only half of the "bug", I would suggest that
>   - the modules 'getdelim', 'getline' guarantee only what POSIX guarantees,
>   - there is no module 'getdelim-gnu'.

Oh right. I was focusing on making the behavior consistent, but I think
agree with you now since the module is not named 'getdelim-gnu'.

How about this patch? It mostly reverts my earlier changes. However, I
kept the ./configure test changes that moved to this idiom:

   int result = 0;
   if (/* Some check that fails.  */)
     result |= 2;
   if (/* Some other check that fails.  */)
     result |= 4;

Since I find it very helpful when trying to understand a function is
replaced and what issues a platform has.

> So, getdelim.m4 should be changed so that all three implementations are
> accepted:
>   - the one from glibc 2.42, musl, OpenBSD, AIX,
>   - the one from macOS, FreeBSD, Solaris,
>   - the one from glibc 2.43,
> and none of these system functions gets overridden.

I tested this patch on glibc 2.42 and glibc 2.43 the function does not
get replaced.

I also tested it on FreeBSD 15.0, Solaris 11.4, and OpenBSD 7.8 and
confirm they do not get replaced there too. They also all pass 'make
check'. I didn't bother testing MacOS since we replace getdelim
unconditionally because of an uninitialized read.

Collin

>From 7f12b242cbf9a1da87a054b6804e870beb62efcb Mon Sep 17 00:00:00 2001
Message-ID: <7f12b242cbf9a1da87a054b6804e870beb62efcb.1769146489.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Thu, 22 Jan 2026 21:15:29 -0800
Subject: [PATCH] getdelim, getline: Don't replace these functions on glibc.

This largely reverts my 2025-10-10 commits since POSIX has relaxed the
requirements to make glibc's behavior compliant. See:
<https://www.austingroupbugs.net/bug_view_page.php?bug_id=1953>.

* doc/posix-functions/getdelim.texi: Move the text about glibc 2.42
to under "Portability problems not fixed by Gnulib".
* doc/posix-functions/getline.texi: Likewise.
* m4/getdelim.m4 (gl_FUNC_GETDELIM): Remove the test on an empty file.
* m4/getline.m4 (gl_FUNC_GETLINE): Likewise.
* tests/test-getdelim.c (main): Remove the test case.
* tests/test-getline.c (main): Likewise.
---
 ChangeLog                         | 12 +++++++++
 doc/posix-functions/getdelim.texi | 10 +++----
 doc/posix-functions/getline.texi  | 10 +++----
 m4/getdelim.m4                    | 43 ++++++++++++++-----------------
 m4/getline.m4                     | 43 ++++++++++++++-----------------
 tests/test-getdelim.c             |  4 ---
 tests/test-getline.c              |  4 ---
 7 files changed, 60 insertions(+), 66 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2444097d60..29bd6c6200 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2026-01-22  Collin Funk  <[email protected]>
 
+	getdelim, getline: Don't replace these functions on glibc.
+	This largely reverts my 2025-10-10 commits since POSIX has relaxed the
+	requirements to make glibc's behavior compliant. See:
+	<https://www.austingroupbugs.net/bug_view_page.php?bug_id=1953>.
+	* doc/posix-functions/getdelim.texi: Move the text about glibc 2.42
+	to under "Portability problems not fixed by Gnulib".
+	* doc/posix-functions/getline.texi: Likewise.
+	* m4/getdelim.m4 (gl_FUNC_GETDELIM): Remove the test on an empty file.
+	* m4/getline.m4 (gl_FUNC_GETLINE): Likewise.
+	* tests/test-getdelim.c (main): Remove the test case.
+	* tests/test-getline.c (main): Likewise.
+
 	doc: document a portability issue with macOS getrusage.
 	* doc/posix-functions/getrusage.texi: Document that the 'ru_maxrss'
 	field of 'struct rusage' is measured in bytes on macOS.
diff --git a/doc/posix-functions/getdelim.texi b/doc/posix-functions/getdelim.texi
index 5801452212..abccdd0496 100644
--- a/doc/posix-functions/getdelim.texi
+++ b/doc/posix-functions/getdelim.texi
@@ -19,11 +19,6 @@ @node getdelim
 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:
@@ -31,4 +26,9 @@ @node getdelim
 @item
 This function has quadratic running time for long lines on some platforms:
 uClibc 0.9.31.
+@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
diff --git a/doc/posix-functions/getline.texi b/doc/posix-functions/getline.texi
index cfef3c8867..48281a9168 100644
--- a/doc/posix-functions/getline.texi
+++ b/doc/posix-functions/getline.texi
@@ -22,11 +22,6 @@ @node getline
 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:
@@ -34,4 +29,9 @@ @node getline
 @item
 This function has quadratic running time for long lines on some platforms:
 uClibc 0.9.31.
+@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
diff --git a/m4/getdelim.m4 b/m4/getdelim.m4
index 8b6eff47aa..736c4e8b2e 100644
--- a/m4/getdelim.m4
+++ b/m4/getdelim.m4
@@ -1,5 +1,5 @@
 # getdelim.m4
-# serial 21
+# serial 22
 
 dnl Copyright (C) 2005-2007, 2009-2026 Free Software Foundation, Inc.
 dnl
@@ -37,7 +37,6 @@ AC_DEFUN([gl_FUNC_GETDELIM]
            gl_cv_func_working_getdelim=no ;;
          *)
            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>
@@ -68,36 +67,32 @@ AC_DEFUN([gl_FUNC_GETDELIM]
         free (line);
       }
       fclose (in);
-      {
-        /* 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 (getdelim (&line, &siz, '\n', in) != -1 || line[0] != '\0')
-          result |= 8;
-        free (line);
-      }
-      fclose (in);
       return result;
     }
     ]])],
              [gl_cv_func_working_getdelim=yes],
              [gl_cv_func_working_getdelim=no],
-             [case "$host_os" in
-                                    # Guess yes on musl.
-                *-musl* | midipix*) gl_cv_func_working_getdelim="guessing yes" ;;
-                                    # Guess no on glibc.
-                *-gnu* | gnu*)      gl_cv_func_working_getdelim="guessing no" ;;
-                *)                  gl_cv_func_working_getdelim="$gl_cross_guess_normal" ;;
-              esac
+             [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
+                ],
+                [gl_cv_func_working_getdelim="guessing yes"],
+                [case "$host_os" in
+                   *-musl* | midipix*) gl_cv_func_working_getdelim="guessing yes" ;;
+                   *)                  gl_cv_func_working_getdelim="$gl_cross_guess_normal" ;;
+                 esac
+                ])
              ])
            ;;
        esac
-       rm -f conftest.data conftest.empty
+       rm -f conftest.data
       ])
     case "$gl_cv_func_working_getdelim" in
       *yes) ;;
diff --git a/m4/getline.m4 b/m4/getline.m4
index ed32fa10bf..25539dc20c 100644
--- a/m4/getline.m4
+++ b/m4/getline.m4
@@ -1,5 +1,5 @@
 # getline.m4
-# serial 35
+# serial 36
 
 dnl Copyright (C) 1998-2003, 2005-2007, 2009-2026 Free Software Foundation,
 dnl Inc.
@@ -31,7 +31,6 @@ 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>
@@ -62,34 +61,30 @@ AC_DEFUN([gl_FUNC_GETLINE]
         free (line);
       }
       fclose (in);
-      {
-        /* 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],
-         [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
+         [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
+            ])
          ])
-       rm -f conftest.data conftest.empty
+       rm -f conftest.data
       ])
   else
     am_cv_func_working_getline=no
diff --git a/tests/test-getdelim.c b/tests/test-getdelim.c
index d472285c5e..25b53ee1d5 100644
--- a/tests/test-getdelim.c
+++ b/tests/test-getdelim.c
@@ -84,11 +84,7 @@ main (void)
   ASSERT (memcmp (line, "d\0f", 4) == 0);
   ASSERT (3 < len);
 
-  /* Test that reading an EOF will terminate the buffer with a NUL
-     character.  */
   result = getdelim (&line, &len, 'n', f);
-  ASSERT (0 < len);
-  ASSERT (line[0] == '\0');
   ASSERT (result == -1);
 
   free (line);
diff --git a/tests/test-getline.c b/tests/test-getline.c
index 8572611d65..eda571eeed 100644
--- a/tests/test-getline.c
+++ b/tests/test-getline.c
@@ -84,11 +84,7 @@ main (void)
   ASSERT (memcmp (line, "d\0f", 4) == 0);
   ASSERT (3 < len);
 
-  /* Test that reading an EOF will terminate the buffer with a NUL
-     character.  */
   result = getline (&line, &len, f);
-  ASSERT (0 < len);
-  ASSERT (line[0] == '\0');
   ASSERT (result == -1);
 
   free (line);
-- 
2.52.0

Reply via email to