[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-tar] getline() differences FreeBSD / GNU libc
From: |
Bruno Haible |
Subject: |
Re: [Bug-tar] getline() differences FreeBSD / GNU libc |
Date: |
Sun, 31 Jan 2010 17:43:12 +0100 |
User-agent: |
KMail/1.9.9 |
> 2010-01-31 Bruno Haible <address@hidden>
>
> Work around getline() bug on FreeBSD 8.0.
> * m4/getline.m4 (gl_FUNC_GETLINE): Also test result for a NULL buffer
> and a non-zero size.
> * tests/test-getline.c (main): Likewise.
> * doc/posix-functions/getline.texi: Mention the FreeBSD bug.
> Reported by Dennis <address@hidden> via Eric Blake.
And similarly for getdelim.
2010-01-31 Bruno Haible <address@hidden>
Work around getdelim() bug on FreeBSD 8.0.
* m4/getdelim.m4 (gl_FUNC_GETDELIM): Test whether getdelim supports an
initially NULL line. Set REPLACE_GETDELIM if getdelim exists but does
not work.
* lib/stdio.in.h (getdelim): Define as an alias if REPLACE_GETDELIM
is 1.
* m4/stdio_h.m4 (gl_STDIO_H_DEFAULTS): Initialize REPLACE_GETDELIM.
* modules/stdio (Makefile.am): Also substitute REPLACE_GETDELIM.
* tests/test-getdelim.c (main): Also test result for a NULL buffer and
a non-zero size.
* doc/posix-functions/getdelim.texi: Mention the FreeBSD bug.
--- doc/posix-functions/getdelim.texi.orig Sun Jan 31 17:33:06 2010
+++ doc/posix-functions/getdelim.texi Sun Jan 31 17:30:59 2010
@@ -14,6 +14,10 @@
@item
This function is missing a declaration on some platforms:
BeOS.
address@hidden
+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.
@end itemize
Portability problems not fixed by Gnulib:
--- lib/stdio.in.h.orig Sun Jan 31 17:33:06 2010
+++ lib/stdio.in.h Sun Jan 31 17:30:59 2010
@@ -340,7 +340,11 @@
#endif
#if @GNULIB_GETDELIM@
-# if address@hidden@
+# if @REPLACE_GETDELIM@
+# undef getdelim
+# define getdelim rpl_getdelim
+# endif
+# if address@hidden@ || @REPLACE_GETDELIM@
/* Read input, up to (and including) the next occurrence of DELIMITER, from
STREAM, store it in *LINEPTR (and NUL-terminate it).
*LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE
--- m4/getdelim.m4.orig Sun Jan 31 17:33:06 2010
+++ m4/getdelim.m4 Sun Jan 31 17:30:59 2010
@@ -1,6 +1,6 @@
-# getdelim.m4 serial 5
+# getdelim.m4 serial 6
-dnl Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2007, 2009-2010 Free Software Foundation, Inc.
dnl
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -15,16 +15,71 @@
dnl Persuade glibc <stdio.h> to declare getdelim().
AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
- AC_REPLACE_FUNCS([getdelim])
AC_CHECK_DECLS_ONCE([getdelim])
- if test $ac_cv_func_getdelim = no; then
- gl_PREREQ_GETDELIM
+ AC_CHECK_FUNCS_ONCE([getdelim])
+ if test $ac_cv_func_getdelim = yes; then
+ dnl Found it in some library. Verify that it works.
+ AC_CACHE_CHECK([for working getdelim function],
[gl_cv_func_working_getdelim],
+ [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+ int main ()
+ {
+ FILE *in = fopen ("./conftest.data", "r");
+ if (!in)
+ return 1;
+ {
+ /* Test result for a NULL buffer and a zero size.
+ Based on a test program from Karl Heuer. */
+ char *line = NULL;
+ size_t siz = 0;
+ int len = getdelim (&line, &siz, '\n', in);
+ if (!(len == 4 && line && strcmp (line, "foo\n") == 0))
+ return 1;
+ }
+ {
+ /* Test result for a NULL buffer and a non-zero size.
+ This crashes on FreeBSD 8.0. */
+ char *line = NULL;
+ size_t siz = (size_t)(~0) / 4;
+ if (getdelim (&line, &siz, '\n', in) == -1)
+ return 1;
+ }
+ return 0;
+ }
+ ]])], [gl_cv_func_working_getdelim=yes] dnl The library version works.
+ , [gl_cv_func_working_getdelim=no] dnl The library version does NOT work.
+ , dnl We're cross compiling. Assume it works on glibc2 systems.
+ [AC_EGREP_CPP([Lucky GNU user],
+ [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ >= 2)
+ Lucky GNU user
+ #endif
+#endif
+ ],
+ [gl_cv_func_working_getdelim=yes],
+ [gl_cv_func_working_getdelim=no])]
+ )])
+ else
+ gl_cv_func_working_getdelim=no
fi
if test $ac_cv_have_decl_getdelim = no; then
HAVE_DECL_GETDELIM=0
fi
+
+ if test $gl_cv_func_working_getdelim = no; then
+ if test $ac_cv_func_getdelim = yes; then
+ REPLACE_GETDELIM=1
+ fi
+ AC_LIBOBJ([getdelim])
+ gl_PREREQ_GETDELIM
+ fi
])
# Prerequisites of lib/getdelim.c.
--- m4/stdio_h.m4.orig Sun Jan 31 17:33:06 2010
+++ m4/stdio_h.m4 Sun Jan 31 17:30:59 2010
@@ -1,4 +1,4 @@
-# stdio_h.m4 serial 24
+# stdio_h.m4 serial 25
dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -111,6 +111,7 @@
REPLACE_FSEEKO=0; AC_SUBST([REPLACE_FSEEKO])
REPLACE_FTELL=0; AC_SUBST([REPLACE_FTELL])
REPLACE_FTELLO=0; AC_SUBST([REPLACE_FTELLO])
+ REPLACE_GETDELIM=0; AC_SUBST([REPLACE_GETDELIM])
REPLACE_GETLINE=0; AC_SUBST([REPLACE_GETLINE])
REPLACE_OBSTACK_PRINTF=0; AC_SUBST([REPLACE_OBSTACK_PRINTF])
REPLACE_PERROR=0; AC_SUBST([REPLACE_PERROR])
--- modules/stdio.orig Sun Jan 31 17:33:06 2010
+++ modules/stdio Sun Jan 31 17:30:59 2010
@@ -89,6 +89,7 @@
-e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \
-e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \
-e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \
+ -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \
-e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \
-e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \
-e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \
--- tests/test-getdelim.c.orig Sun Jan 31 17:33:06 2010
+++ tests/test-getdelim.c Sun Jan 31 17:30:59 2010
@@ -33,13 +33,13 @@
main (void)
{
FILE *f;
- char *line = NULL;
- size_t len = 0;
+ char *line;
+ size_t len;
ssize_t result;
/* Create test file. */
f = fopen ("test-getdelim.txt", "wb");
- if (!f || fwrite ("anbcnd\0f", 1, 8, f) != 8 || fclose (f) != 0)
+ if (!f || fwrite ("anAnbcnd\0f", 1, 10, f) != 10 || fclose (f) != 0)
{
fputs ("Failed to create sample file.\n", stderr);
remove ("test-getdelim.txt");
@@ -54,13 +54,24 @@
}
/* Test initial allocation, which must include trailing NUL. */
+ line = NULL;
+ len = 0;
result = getdelim (&line, &len, 'n', f);
ASSERT (result == 2);
ASSERT (strcmp (line, "an") == 0);
ASSERT (2 < len);
+ free (line);
- /* Test growth of buffer. */
+ /* Test initial allocation again, with line = NULL and len != 0. */
+ line = NULL;
+ len = (size_t)(~0) / 4;
+ result = getdelim (&line, &len, 'n', f);
+ ASSERT (result == 2);
+ ASSERT (strcmp (line, "An") == 0);
+ ASSERT (2 < len);
free (line);
+
+ /* Test growth of buffer. */
line = malloc (1);
len = 1;
result = getdelim (&line, &len, 'n', f);