1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

ensure that errno is not modified inside Curl_strerror()

This commit is contained in:
Yang Tse 2008-09-12 10:51:57 +00:00
parent 77bafd823b
commit c3d1b07c45

View File

@ -24,10 +24,11 @@
#include "setup.h" #include "setup.h"
#ifdef HAVE_STRERROR_R #ifdef HAVE_STRERROR_R
#if !defined(HAVE_POSIX_STRERROR_R) && !defined(HAVE_GLIBC_STRERROR_R) # if (!defined(HAVE_POSIX_STRERROR_R) && !defined(HAVE_GLIBC_STRERROR_R)) || \
#error "you MUST have either POSIX or glibc strerror_r if strerror_r is found" (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
#endif /* !POSIX && !glibc */ # error "strerror_r MUST be either POSIX-style or glibc-style"
#endif /* HAVE_STRERROR_R */ # endif
#endif
#include <curl/curl.h> #include <curl/curl.h>
#include <stdlib.h> #include <stdlib.h>
@ -43,14 +44,6 @@
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
#if defined(HAVE_STRERROR_R) && defined(HAVE_NO_STRERROR_R_DECL)
#ifdef HAVE_POSIX_STRERROR_R
/* seen on AIX 5100-02 gcc 2.9 */
extern int strerror_r(int errnum, char *strerrbuf, size_t buflen);
#else
extern char *strerror_r(int errnum, char *buf, size_t buflen);
#endif
#endif
const char * const char *
curl_easy_strerror(CURLcode error) curl_easy_strerror(CURLcode error)
@ -590,6 +583,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
{ {
char *buf, *p; char *buf, *p;
size_t max; size_t max;
int old_errno = ERRNO;
DEBUGASSERT(conn); DEBUGASSERT(conn);
DEBUGASSERT(err >= 0); DEBUGASSERT(err >= 0);
@ -601,17 +595,15 @@ const char *Curl_strerror(struct connectdata *conn, int err)
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
buf[0]=0;
{ {
wchar_t wbuf[256]; wchar_t wbuf[256];
wbuf[0] = L'\0';
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL);
wcstombs(buf,wbuf,max); wcstombs(buf,wbuf,max);
} }
#else #else
/* 'sys_nerr' is the maximum errno number, it is not widely portable */ /* 'sys_nerr' is the maximum errno number, it is not widely portable */
if(err >= 0 && err < sys_nerr) if(err >= 0 && err < sys_nerr)
strncpy(buf, strerror(err), max); strncpy(buf, strerror(err), max);
@ -622,34 +614,43 @@ const char *Curl_strerror(struct connectdata *conn, int err)
snprintf(buf, max, "Unknown error %d (%#x)", err, err); snprintf(buf, max, "Unknown error %d (%#x)", err, err);
} }
#endif #endif
#else /* not USE_WINSOCK coming up */ #else /* not USE_WINSOCK coming up */
/* These should be atomic and hopefully thread-safe */ #if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
#ifdef HAVE_STRERROR_R /*
/* There are two different APIs for strerror_r(). The POSIX and the GLIBC * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
versions. */ * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
#ifdef HAVE_POSIX_STRERROR_R * message string, or EINVAL if 'errnum' is not a valid error number.
strerror_r(err, buf, max); */
/* this may set errno to ERANGE if insufficient storage was supplied via if(0 != strerror_r(err, buf, max)) {
'strerrbuf' and 'buflen' to contain the generated message string, or if('\0' == buf[0])
EINVAL if the value of 'errnum' is not a valid error number.*/ snprintf(buf, max, "Unknown error %d", err);
#else }
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
/*
* The glibc-style strerror_r() only *might* use the buffer we pass to
* the function, but it always returns the error message as a pointer,
* so we must copy that string unconditionally (if non-NULL).
*/
{ {
/* HAVE_GLIBC_STRERROR_R */
char buffer[256]; char buffer[256];
char *msg = strerror_r(err, buffer, sizeof(buffer)); char *msg = strerror_r(err, buffer, sizeof(buffer));
/* this version of strerror_r() only *might* use the buffer we pass to
the function, but it always returns the error message as a pointer,
so we must copy that string unconditionally (if non-NULL) */
if(msg) if(msg)
strncpy(buf, msg, max); strncpy(buf, msg, max);
else else
snprintf(buf, max, "Unknown error %d", err); snprintf(buf, max, "Unknown error %d", err);
} }
#endif /* end of HAVE_GLIBC_STRERROR_R */ #else
#else /* HAVE_STRERROR_R */ {
strncpy(buf, strerror(err), max); char *msg = strerror(err);
#endif /* end of HAVE_STRERROR_R */ if(msg)
strncpy(buf, msg, max);
else
snprintf(buf, max, "Unknown error %d", err);
}
#endif
#endif /* end of ! USE_WINSOCK */ #endif /* end of ! USE_WINSOCK */
buf[max] = '\0'; /* make sure the string is zero terminated */ buf[max] = '\0'; /* make sure the string is zero terminated */
@ -659,6 +660,10 @@ const char *Curl_strerror(struct connectdata *conn, int err)
*p = '\0'; *p = '\0';
if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1) if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
*p = '\0'; *p = '\0';
if(old_errno != ERRNO)
SET_ERRNO(old_errno);
return buf; return buf;
} }
@ -680,6 +685,7 @@ const char *Curl_idn_strerror (struct connectdata *conn, int err)
buf = conn->syserr_buf; buf = conn->syserr_buf;
max = sizeof(conn->syserr_buf)-1; max = sizeof(conn->syserr_buf)-1;
*buf = '\0';
#ifndef CURL_DISABLE_VERBOSE_STRINGS #ifndef CURL_DISABLE_VERBOSE_STRINGS
switch ((Idna_rc)err) { switch ((Idna_rc)err) {