Mercurial > hg > octave-kai > gnulib-hg
changeset 14762:3c012e3d3f43
strerror: enforce POSIX ruling on strerror(0)
http://austingroupbugs.net/view.php?id=382 requires that strerror(0)
succeed, but FreeBSD reports "Unknown error: 0" and fails with EINVAL.
* m4/strerror.m4 (gl_FUNC_STRERROR_SEPARATE): Expose BSD bug.
* m4/strerror_r.m4 (gl_FUNC_STRERROR_R): Likewise.
* lib/strerror_r.c (rpl_strerror_r): Work around it.
* doc/posix-functions/strerror.texi (strerror): Document it.
* doc/posix-functions/strerror_r.texi (strerror_r): Likewise.
* tests/test-strerror.c (main): Strengthen test.
* tests/test-strerror_r.c (main): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
author | Eric Blake <eblake@redhat.com> |
---|---|
date | Wed, 18 May 2011 18:16:59 -0600 |
parents | 6c5502aeb486 |
children | 19cd3c889b58 |
files | ChangeLog doc/posix-functions/strerror.texi doc/posix-functions/strerror_r.texi lib/strerror_r.c m4/strerror.m4 m4/strerror_r.m4 tests/test-strerror.c tests/test-strerror_r.c |
diffstat | 8 files changed, 89 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-05-19 Eric Blake <eblake@redhat.com> + + strerror: enforce POSIX ruling on strerror(0) + * m4/strerror.m4 (gl_FUNC_STRERROR_SEPARATE): Expose BSD bug. + * m4/strerror_r.m4 (gl_FUNC_STRERROR_R): Likewise. + * lib/strerror_r.c (rpl_strerror_r): Work around it. + * doc/posix-functions/strerror.texi (strerror): Document it. + * doc/posix-functions/strerror_r.texi (strerror_r): Likewise. + * tests/test-strerror.c (main): Strengthen test. + * tests/test-strerror_r.c (main): Likewise. + 2011-05-19 Paul Eggert <eggert@cs.ucla.edu> intprop-tests: port to older and more-pedantic compilers
--- a/doc/posix-functions/strerror.texi +++ b/doc/posix-functions/strerror.texi @@ -13,11 +13,18 @@ but not defined by the system, on some platforms: OpenBSD 4.0, OSF/1 5.1, NonStop Kernel, Cygwin 1.5.x, mingw. @item +This function reports failure (by setting @code{errno}) for +@code{strerror(0)}, although POSIX requires this to leave @code{errno} +unchanged and report success, on some platforms: +FreeBSD 8.2 +@item This function fails to return a string for out-of-range integers on some platforms: HP-UX 11, IRIX 6.5, Solaris 8. -(This is not a POSIX violation, but can still cause bugs because most programs -call @code{strerror} without setting and testing @code{errno}.) +(Some return NULL which is a POSIX violation, others return the empty +string which is valid but not as useful); this can still cause bugs +because most programs call @code{strerror} without setting and testing +@code{errno}.) @end itemize Portability problems not fixed by Gnulib:
--- a/doc/posix-functions/strerror_r.texi +++ b/doc/posix-functions/strerror_r.texi @@ -37,6 +37,10 @@ but not defined by the system, on some platforms: OpenBSD 4.0, OSF/1 5.1, NonStop Kernel, Cygwin 1.5.x. @item +This function reports failure for @code{strerror_r(0, buf, len)}, +although POSIX requires this to succeed, on some platforms: +FreeBSD 8.2 +@item This function always fails when the third argument is less than 80 on some platforms: HP-UX 11.31.
--- a/lib/strerror_r.c +++ b/lib/strerror_r.c @@ -436,6 +436,22 @@ if (ret < 0) ret = errno; + /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382. */ + if (errnum == 0 && ret == EINVAL) + { + if (buflen <= strlen ("Success")) + { + ret = ERANGE; + if (buflen) + buf[0] = 0; + } + else + { + ret = 0; + strcpy (buf, "Success"); + } + } + #elif USE_XPG_STRERROR_R {
--- a/m4/strerror.m4 +++ b/m4/strerror.m4 @@ -1,4 +1,4 @@ -# strerror.m4 serial 9 +# strerror.m4 serial 10 dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -25,19 +25,18 @@ [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include <string.h> + #include <errno.h> ]], - [[return !*strerror (-2);]])], + [[int result = 0; + if (!*strerror (-2)) result |= 1; + errno = 0; + if (!*strerror (0)) result |= 2; + if (errno) result |= 4; + return result;]])], [gl_cv_func_working_strerror=yes], [gl_cv_func_working_strerror=no], - [dnl Assume crossbuild works if it compiles. - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include <string.h> - ]], - [[return !*strerror (-2);]])], - [gl_cv_func_working_strerror=yes], - [gl_cv_func_working_strerror=no]) - ]) + [dnl Be pessimistic on cross-compiles for now. + gl_cv_func_working_strerror=no]) ]) if test $gl_cv_func_working_strerror = no; then dnl The system's strerror() fails to return a string for out-of-range
--- a/m4/strerror_r.m4 +++ b/m4/strerror_r.m4 @@ -1,4 +1,4 @@ -# strerror_r.m4 serial 3 +# strerror_r.m4 serial 4 dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -41,6 +41,7 @@ dnl AIX 6.1 strerror_r fails by returning -1, not an error number. dnl HP-UX 11.31 strerror_r always fails when the buffer length argument dnl is less than 80. + dnl FreeBSD 8.s strerror_r claims failure on 0 AC_CACHE_CHECK([whether strerror_r works], [gl_cv_func_strerror_r_works], [AC_RUN_IFELSE( @@ -53,8 +54,13 @@ char buf[79]; if (strerror_r (EACCES, buf, 0) < 0) result |= 1; - if (strerror_r (EACCES, buf, sizeof (buf)) != 0) + errno = 0; + if (strerror_r (EACCES, buf, sizeof buf) != 0) result |= 2; + if (strerror_r (0, buf, sizeof buf) != 0) + result |= 4; + if (errno) + result |= 8; return result; ]])], [gl_cv_func_strerror_r_works=yes], @@ -66,6 +72,8 @@ aix*) gl_cv_func_strerror_r_works="guessing no";; # Guess no on HP-UX. hpux*) gl_cv_func_strerror_r_works="guessing no";; + # Guess no on FreeBSD. + freebsd*) gl_cv_func_strerror_r_works="guessing no";; # Guess yes otherwise. *) gl_cv_func_strerror_r_works="guessing yes";; esac @@ -78,7 +86,7 @@ else dnl The system's strerror() has a wrong signature. Replace it. REPLACE_STRERROR_R=1 - dnl glibc >= 2.3.4 has a function __xpg_strerror_r. + dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r. AC_CHECK_FUNCS([__xpg_strerror_r]) fi else
--- a/tests/test-strerror.c +++ b/tests/test-strerror.c @@ -33,25 +33,43 @@ { char *str; + errno = 0; str = strerror (EACCES); ASSERT (str); ASSERT (*str); + ASSERT (errno == 0); + errno = 0; str = strerror (ETIMEDOUT); ASSERT (str); ASSERT (*str); + ASSERT (errno == 0); + errno = 0; str = strerror (EOVERFLOW); ASSERT (str); ASSERT (*str); + ASSERT (errno == 0); + /* POSIX requires strerror (0) to succeed; use of "Unknown error" or + "error 0" does not count as success, but "No error" works. + http://austingroupbugs.net/view.php?id=382 */ + errno = 0; str = strerror (0); ASSERT (str); ASSERT (*str); + ASSERT (errno == 0); + ASSERT (strchr (str, '0') == NULL); + ASSERT (strstr (str, "nknown") == NULL); + /* POSIX requires strerror to produce a non-NULL result for all + inputs; as an extension, we also guarantee a non-empty reseult. + Reporting EINVAL is optional. */ + errno = 0; str = strerror (-3); ASSERT (str); ASSERT (*str); + ASSERT (errno == 0 || errno == EINVAL); return 0; }
--- a/tests/test-strerror_r.c +++ b/tests/test-strerror_r.c @@ -46,13 +46,17 @@ ASSERT (strerror_r (EOVERFLOW, buf, sizeof (buf)) == 0); ASSERT (buf[0] != '\0'); - /* Test results with out-of-range errnum and enough room. */ - - buf[0] = '^'; + /* POSIX requires strerror (0) to succeed; use of "Unknown error" or + "error 0" does not count as success, but "No error" works. + http://austingroupbugs.net/view.php?id=382 */ + buf[0] = '\0'; ret = strerror_r (0, buf, sizeof (buf)); - ASSERT (ret == 0 || ret == EINVAL); - if (ret == 0) - ASSERT (buf[0] != '^'); + ASSERT (ret == 0); + ASSERT (buf[0]); + ASSERT (strchr (buf, '0') == NULL); + ASSERT (strstr (buf, "nknown") == NULL); + + /* Test results with out-of-range errnum and enough room. */ buf[0] = '^'; ret = strerror_r (-3, buf, sizeof (buf));