Bug 12204 - glibc does has no POSIX compliant strerror_r function
Summary: glibc does has no POSIX compliant strerror_r function
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.8
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks: 12782
  Show dependency treegraph
 
Reported: 2010-11-09 23:14 UTC by Bruno Haible
Modified: 2014-06-30 06:29 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
test case (249 bytes, text/plain)
2010-11-09 23:17 UTC, Bruno Haible
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bruno Haible 2010-11-09 23:14:33 UTC
glibc has two strerror_r functions, declared in <string.h> depending on
feature macros. But none of them is POSIX compliant.

The one which is in effect when _GNU_SOURCE=1 has the declaration
char *strerror_r (int, char *, size_t). It has a different return type
and therefore a different calling convention than the POSIX function.
Test case:
=================================================
#define _GNU_SOURCE 1
#include <string.h>
#include <stdio.h>

int main()
{
  char buf[100];
  char *s = strerror_r (-2, buf, sizeof (buf));
  printf ("result: %s\n", s);
  return 0;
}
=================================================

The one which is in effect when _GNU_SOURCE is undefined and
_POSIX_C_SOURCE=200112L has the declaration
int strerror_r (int, char *, size_t), which is POSIX compatible,
but it has a different return value convention in case of failure.
POSIX:2001 and POSIX:2008 say that in case of failure the strerror_r
function should return "an error number"; this is the same wording
as for pthread_create, pthread_mutex_lock, etc. However, the glibc
function returns -1 and sets errno to the error number instead.
Test case:
========================================================================
#define _POSIX_C_SOURCE 200112L
#include <string.h>
#include <errno.h>
#include <stdio.h>

int main()
{
  char buf[100] = "______";
  int r;

  r = strerror_r (-2, buf, sizeof (buf));
  if (r == 0)
    printf ("result: success %s\n", buf);
  else if (r > 0)
    printf ("result: failure %d %s\n", r, buf);
  else
    printf ("result: non-POSIX failure %d %d %s\n", r, errno, buf);

  r = strerror_r (EACCES, buf, 3);
  if (r == 0)
    printf ("result: success %s\n", buf);
  else if (r > 0)
    printf ("result: failure %d %s\n", r, buf);
  else
    printf ("result: non-POSIX failure %d %d %s\n", r, errno, buf);

  return 0;
}
==========================================================================
Expected result:
result: failure 22 ______
result: failure 34 ______

Actual result:
result: non-POSIX failure -1 22 ______
result: non-POSIX failure -1 34 ______
Comment 1 Bruno Haible 2010-11-09 23:17:17 UTC
Created attachment 5117 [details]
test case
Comment 2 Bruno Haible 2010-11-09 23:20:25 UTC
The fix could either be to change the behaviour of __xpg_strerror_r
so that it returns the error number instead of assigning it to errno,
or to introduce a new function __posix_strerror_r and enable it in <string.h>
under the appropriate conditions.
Comment 3 Ulrich Drepper 2010-11-10 08:14:11 UTC
What do other OSes do?  What's the behavior on Solaris?  Common practice IIRC was at least to return -1.  Might just be that the incorrect wording was copied into the strerror_r spec.
Comment 4 Andreas Schwab 2010-11-10 09:10:45 UTC
According to http://www.freebsd.org/cgi/man.cgi *BSD and Solaris both return the error number.
Comment 5 Bruno Haible 2010-11-11 09:36:21 UTC
> What do other OSes do?  What's the behavior on Solaris?

Here are the results of the test program:

Solaris 10:
result: failure 22 Unknown error
result: failure 34 Unknown error

FreeBSD 6.4, OpenBSD 4.4:
result: failure 22 Unknown error: -2
result: failure 34 Pe

HP-UX 11.31:
result: failure 22 ______
result: failure 34 ______

AIX 6.1:
result: success Error -2 occurred.
result: success Pe

Tru64 5.1:
result: non-POSIX failure -1 22 Error -2 occurred.
result: success Pe

You can see that the major Unices use the POSIX compliant return value
convention. Tru64 is the only one to use the (-1,errno) return value.
Comment 6 Ulrich Drepper 2010-12-25 18:57:57 UTC
I've changed the __xpg_strerror_r implementations.
Comment 7 dank 2013-02-08 19:35:04 UTC
See also http://austingroupbugs.net/view.php?id=655
Looks like strerror_r is being retired because of the confusion.
Comment 8 Jackie Rosen 2014-02-16 18:28:06 UTC Comment hidden (spam)