forked from pool/openssl-1_1
51 lines
1.7 KiB
Diff
51 lines
1.7 KiB
Diff
|
diff --git a/crypto/o_str.c b/crypto/o_str.c
|
||
|
index 02578dbf0d..3b271e745b 100644
|
||
|
--- a/crypto/o_str.c
|
||
|
+++ b/crypto/o_str.c
|
||
|
@@ -223,7 +223,26 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
|
||
|
#if defined(_MSC_VER) && _MSC_VER>=1400
|
||
|
return !strerror_s(buf, buflen, errnum);
|
||
|
#elif defined(_GNU_SOURCE)
|
||
|
- return strerror_r(errnum, buf, buflen) != NULL;
|
||
|
+ char *err;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * GNU strerror_r may not actually set buf.
|
||
|
+ * It can return a pointer to some (immutable) static string in which case
|
||
|
+ * buf is left unused.
|
||
|
+ */
|
||
|
+ err = strerror_r(errnum, buf, buflen);
|
||
|
+ if (err == NULL)
|
||
|
+ return 0;
|
||
|
+ /*
|
||
|
+ * If err is statically allocated, err != buf and we need to copy the data.
|
||
|
+ * If err points somewhere inside buf, OPENSSL_strlcpy can handle this,
|
||
|
+ * since src and dest are not annotated with __restrict and the function
|
||
|
+ * reads src byte for byte and writes to dest.
|
||
|
+ * If err == buf we do not have to copy anything.
|
||
|
+ */
|
||
|
+ if (err != buf)
|
||
|
+ OPENSSL_strlcpy(buf, err, buflen);
|
||
|
+ return 1;
|
||
|
#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
|
||
|
(defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
|
||
|
/*
|
||
|
@@ -234,6 +253,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
|
||
|
return !strerror_r(errnum, buf, buflen);
|
||
|
#else
|
||
|
char *err;
|
||
|
+
|
||
|
/* Fall back to non-thread safe strerror()...its all we can do */
|
||
|
if (buflen < 2)
|
||
|
return 0;
|
||
|
@@ -241,8 +261,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
|
||
|
/* Can this ever happen? */
|
||
|
if (err == NULL)
|
||
|
return 0;
|
||
|
- strncpy(buf, err, buflen - 1);
|
||
|
- buf[buflen - 1] = '\0';
|
||
|
+ OPENSSL_strlcpy(buf, err, buflen);
|
||
|
return 1;
|
||
|
#endif
|
||
|
}
|