[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] strerror: enforce POSIX ruling on strerror(0)
From: |
Eric Blake |
Subject: |
[PATCH] strerror: enforce POSIX ruling on strerror(0) |
Date: |
Thu, 19 May 2011 09:34:26 -0600 |
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 <address@hidden>
---
ChangeLog | 11 +++++++++++
doc/posix-functions/strerror.texi | 11 +++++++++--
doc/posix-functions/strerror_r.texi | 4 ++++
lib/strerror_r.c | 16 ++++++++++++++++
m4/strerror.m4 | 21 ++++++++++-----------
m4/strerror_r.m4 | 14 +++++++++++---
tests/test-strerror.c | 20 +++++++++++++++++++-
tests/test-strerror_r.c | 16 ++++++++++------
8 files changed, 90 insertions(+), 23 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index b21dc1b..8c1200c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2011-05-19 Eric Blake <address@hidden>
+
+ 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 <address@hidden>
intprop-tests: port to older and more-pedantic compilers
diff --git a/doc/posix-functions/strerror.texi
b/doc/posix-functions/strerror.texi
index 68a98da..6f9519a 100644
--- a/doc/posix-functions/strerror.texi
+++ b/doc/posix-functions/strerror.texi
@@ -13,11 +13,18 @@ strerror
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
address@hidden(0)}, although POSIX requires this to leave @code{errno}
+unchanged and report success, on some platforms:
+FreeBSD 8.2
address@hidden
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
address@hidden)
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/strerror_r.texi
b/doc/posix-functions/strerror_r.texi
index bf43164..9d6639e 100644
--- a/doc/posix-functions/strerror_r.texi
+++ b/doc/posix-functions/strerror_r.texi
@@ -37,6 +37,10 @@ strerror_r
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
address@hidden
This function always fails when the third argument is less than 80 on some
platforms:
HP-UX 11.31.
diff --git a/lib/strerror_r.c b/lib/strerror_r.c
index 3bba26c..fc0603c 100644
--- a/lib/strerror_r.c
+++ b/lib/strerror_r.c
@@ -436,6 +436,22 @@ strerror_r (int errnum, char *buf, size_t buflen)
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
{
diff --git a/m4/strerror.m4 b/m4/strerror.m4
index 73d1d54..d891031 100644
--- 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_DEFUN([gl_FUNC_STRERROR_SEPARATE],
[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
diff --git a/m4/strerror_r.m4 b/m4/strerror_r.m4
index 1883458..ca3904c 100644
--- 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 @@ AC_DEFUN([gl_FUNC_STRERROR_R],
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 @@ AC_DEFUN([gl_FUNC_STRERROR_R],
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 @@ changequote(,)dnl
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 @@ changequote([,])dnl
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
diff --git a/tests/test-strerror.c b/tests/test-strerror.c
index 66dbe82..46d339e 100644
--- a/tests/test-strerror.c
+++ b/tests/test-strerror.c
@@ -33,25 +33,43 @@ main (void)
{
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;
}
diff --git a/tests/test-strerror_r.c b/tests/test-strerror_r.c
index b2fdaf9..0661bdf 100644
--- a/tests/test-strerror_r.c
+++ b/tests/test-strerror_r.c
@@ -46,13 +46,17 @@ main (void)
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));
--
1.7.4.4
- [PATCH] strerror: enforce POSIX ruling on strerror(0),
Eric Blake <=