2011-06-21 Eric Blake <eblake@redhat.com>
+ strerror_r: fix OpenBSD behavior on out-of-range
+ * lib/strerror_r.c (strerror_r): Always use maximal string.
+ * doc/posix-functions/strerror_r.texi (strerror_r): Document it.
+
strerror_r: fix OpenBSD behavior on 0
* lib/strerror-override.c (strerror_override): Also override 0
when needed.
function fails to leave a NUL-terminated string in the buffer on some
platforms:
glibc 2.13, FreeBSD 8.2, Solaris 10.
+@item
+When the value is out of range but the buffer is too small, this
+function does not always return the longest possible string on some
+platforms:
+OpenBSD 4.7.
@end itemize
Portability problems not fixed by Gnulib:
ret = strerror_r (errnum, buf, buflen);
}
# else
- /* Solaris 10 does not populate buf on ERANGE. */
ret = strerror_r (errnum, buf, buflen);
- if (ret == ERANGE && !*buf)
- {
- char stackbuf[STACKBUF_LEN];
- if (strerror_r (errnum, stackbuf, sizeof stackbuf) == ERANGE)
- /* STACKBUF_LEN should have been large enough. */
- abort ();
- safe_copy (buf, buflen, stackbuf);
- }
+ /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
+ if (ret < 0)
+ ret = errno;
# endif
# ifdef _AIX
if (buflen <= len)
ret = ERANGE;
}
-# endif
+# else
+ /* Solaris 10 does not populate buf on ERANGE. OpenBSD 4.7
+ truncates early on ERANGE rather than return a partial integer.
+ We prefer the maximal string. We set buf[0] earlier, and we
+ know of no implementation that modifies buf to be an
+ unterminated string, so this strlen should be portable in
+ practice (rather than pulling in a safer strnlen). */
+ if (ret == ERANGE && strlen (buf) < buflen - 1)
+ {
+ char stackbuf[STACKBUF_LEN];
- /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
- if (ret < 0)
- ret = errno;
+ /* STACKBUF_LEN should have been large enough. */
+ if (strerror_r (errnum, stackbuf, sizeof stackbuf) == ERANGE)
+ abort ();
+ safe_copy (buf, buflen, stackbuf);
+ }
+# endif
#else /* USE_SYSTEM_STRERROR */