Allow strerror(0) and strerror_r(0, ...).

Of course, strerror_r() may still fail with ERANGE.

Although the POSIX specification said this could fail with EINVAL and
doing this likely indicates invalid use of errno, most other
implementations permitted it, various POSIX testsuites require it to
work (matching the older sys_errlist array) and apparently some
applications depend on it.

PR:		standards/151316
MFC after:	1 week
This commit is contained in:
Jilles Tjoelker 2011-04-05 21:56:05 +00:00
parent cf696f26c9
commit 2973057493
4 changed files with 19 additions and 11 deletions

View File

@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
const char *const sys_errlist[] = {
"Undefined error: 0", /* 0 - ENOERROR */
"No error: 0", /* 0 - ENOERROR */
"Operation not permitted", /* 1 - EPERM */
"No such file or directory", /* 2 - ENOENT */
"No such process", /* 3 - ESRCH */

View File

@ -32,7 +32,7 @@
.\" @(#)strerror.3 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
.Dd October 12, 2004
.Dd April 5, 2011
.Dt STRERROR 3
.Os
.Sh NAME
@ -114,6 +114,9 @@ the range 0 <
.Fa errnum
<
.Fa sys_nerr .
The number 0 is also recognized, although applications that take advantage of
this are likely to use unspecified values of
.Va errno .
.Pp
If insufficient storage is provided in
.Fa strerrbuf

View File

@ -87,7 +87,7 @@ strerror_r(int errnum, char *strerrbuf, size_t buflen)
catd = catopen("libc", NL_CAT_LOCALE);
#endif
if (errnum < 1 || errnum >= sys_nerr) {
if (errnum < 0 || errnum >= sys_nerr) {
errstr(errnum,
#if defined(NLS)
catgets(catd, 1, 0xffff, UPREFIX),

View File

@ -42,16 +42,11 @@ main(void)
char *sret;
int iret;
plan_tests(25);
plan_tests(27);
/*
* strerror() failure tests.
*/
errno = 0;
sret = strerror(0);
ok1(strcmp(sret, "Unknown error: 0") == 0);
ok1(errno == EINVAL);
errno = 0;
sret = strerror(INT_MAX);
snprintf(buf, sizeof(buf), "Unknown error: %d", INT_MAX);
@ -61,6 +56,11 @@ main(void)
/*
* strerror() success tests.
*/
errno = 0;
sret = strerror(0);
ok1(strcmp(sret, "No error: 0") == 0);
ok1(errno == 0);
errno = 0;
sret = strerror(EPERM);
ok1(strcmp(sret, "Operation not permitted") == 0);
@ -79,8 +79,8 @@ main(void)
* strerror_r() failure tests.
*/
memset(buf, '*', sizeof(buf));
iret = strerror_r(0, buf, sizeof(buf));
ok1(strcmp(buf, "Unknown error: 0") == 0);
iret = strerror_r(-1, buf, sizeof(buf));
ok1(strcmp(buf, "Unknown error: -1") == 0);
ok1(iret == EINVAL);
memset(buf, '*', sizeof(buf));
@ -116,6 +116,11 @@ main(void)
/*
* strerror_r() success tests.
*/
memset(buf, '*', sizeof(buf));
iret = strerror_r(0, buf, sizeof(buf));
ok1(strcmp(buf, "No error: 0") == 0);
ok1(iret == 0);
memset(buf, '*', sizeof(buf));
iret = strerror_r(EDEADLK, buf, sizeof(buf));
ok1(strcmp(buf, "Resource deadlock avoided") == 0);