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:
parent
77bafd823b
commit
c3d1b07c45
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user