8133249: Occasional SIGSEGV: non thread-safe use of strerr in getLastErrorString
Reviewed-by: igerasim, rriggs, christos
--- a/jdk/make/lib/CoreLibraries.gmk Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/make/lib/CoreLibraries.gmk Thu Oct 01 00:13:09 2015 +0100
@@ -160,6 +160,7 @@
-framework Security -framework SystemConfiguration, \
LDFLAGS_SUFFIX_windows := -export:winFileHandleOpen -export:handleLseek \
-export:getLastErrorString \
+ -export:getErrorString \
jvm.lib $(BUILD_LIBFDLIBM) $(WIN_VERIFY_LIB) \
shell32.lib delayimp.lib -DELAYLOAD:shell32.dll \
advapi32.lib version.lib, \
--- a/jdk/make/mapfiles/libjava/mapfile-vers Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Thu Oct 01 00:13:09 2015 +0100
@@ -282,8 +282,9 @@
# ZipFile.c needs this one
throwFileNotFoundException;
- # zip_util.c needs this one
+ # zip_util.c needs these
getLastErrorString;
+ getErrorString;
# Outcalls from libjvm done using dlsym().
--- a/jdk/src/java.base/share/native/libjava/jni_util.h Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/share/native/libjava/jni_util.h Thu Oct 01 00:13:09 2015 +0100
@@ -388,6 +388,7 @@
char *jniEntryName);
extern size_t getLastErrorString(char *buf, size_t len);
+extern int getErrorString(int err, char *buf, size_t len);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
--- a/jdk/src/java.base/share/native/libzip/zip_util.c Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/share/native/libzip/zip_util.c Thu Oct 01 00:13:09 2015 +0100
@@ -1438,6 +1438,7 @@
ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
{
char *msg;
+ char tmpbuf[1024];
strcpy(entryname, entry->name);
if (entry->csize == 0) {
@@ -1456,8 +1457,11 @@
msg = zip->msg;
ZIP_Unlock(zip);
if (n == -1) {
- jio_fprintf(stderr, "%s: %s\n", zip->name,
- msg != 0 ? msg : strerror(errno));
+ if (msg == 0) {
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ msg = tmpbuf;
+ }
+ jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
return JNI_FALSE;
}
buf += n;
@@ -1470,8 +1474,11 @@
if ((msg == NULL) || (*msg == 0)) {
msg = zip->msg;
}
- jio_fprintf(stderr, "%s: %s\n", zip->name,
- msg != 0 ? msg : strerror(errno));
+ if (msg == 0) {
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ msg = tmpbuf;
+ }
+ jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
return JNI_FALSE;
}
}
--- a/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c Thu Oct 01 00:13:09 2015 +0100
@@ -248,12 +248,13 @@
const char *detail = defaultDetail;
char *errmsg;
size_t fmtsize;
+ char tmpbuf[1024];
jstring s;
if (errnum != 0) {
- const char *s = strerror(errnum);
- if (strcmp(s, "Unknown error") != 0)
- detail = s;
+ int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf));
+ if (ret != EINVAL)
+ detail = tmpbuf;
}
/* ASCII Decimal representation uses 2.4 times as many bits as binary. */
fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum);
--- a/jdk/src/java.base/unix/native/libjava/jni_util_md.c Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/unix/native/libjava/jni_util_md.c Thu Oct 01 00:13:09 2015 +0100
@@ -30,6 +30,13 @@
#include "jni_util.h"
#include "dlfcn.h"
+#if defined(LINUX) && (defined(_GNU_SOURCE) || \
+ (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE < 200112L \
+ && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE < 600))
+extern int __xpg_strerror_r(int, char *, size_t);
+#define strerror_r(a, b, c) __xpg_strerror_r((a), (b), (c))
+#endif
+
void* getProcessHandle() {
static void *procHandle = NULL;
if (procHandle != NULL) {
@@ -55,16 +62,14 @@
size_t
getLastErrorString(char *buf, size_t len)
{
- char *err;
- size_t n;
if (errno == 0 || len < 1) return 0;
+ getErrorString(errno, buf, len);
+ return strlen(buf);
+}
- err = strerror(errno);
- n = strlen(err);
- if (n >= len)
- n = len - 1;
-
- strncpy(buf, err, n);
- buf[n] = '\0';
- return n;
+int
+getErrorString(int err, char *buf, size_t len)
+{
+ if (err == 0 || len < 1) return 0;
+ return strerror_r(err, buf, len);
}
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Thu Oct 01 00:13:09 2015 +0100
@@ -918,6 +918,7 @@
jobject this) {
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
int arg, fd, t = 1;
+ char tmpbuf[1024];
#ifdef AF_INET6
int domain = ipv6_available() ? AF_INET6 : AF_INET;
#else
@@ -953,22 +954,23 @@
arg = 65507;
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
(char *)&arg, sizeof(arg)) < 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- strerror(errno));
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
close(fd);
return;
}
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
(char *)&arg, sizeof(arg)) < 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- strerror(errno));
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
close(fd);
return;
}
#endif /* __APPLE__ */
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof (int)) < 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", strerror(errno));
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
close(fd);
return;
}
@@ -977,9 +979,10 @@
arg = 0;
int level = (domain == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
if ((setsockopt(fd, level, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&
- (errno != ENOPROTOOPT)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- strerror(errno));
+ (errno != ENOPROTOOPT))
+ {
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
close(fd);
return;
}
@@ -994,7 +997,8 @@
int ttl = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &ttl,
sizeof (ttl)) < 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", strerror(errno));
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
close(fd);
return;
}
--- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c Thu Oct 01 00:13:09 2015 +0100
@@ -315,21 +315,15 @@
JNIEXPORT jbyteArray
Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
{
- char* msg;
+ char tmpbuf[1024];
jsize len;
jbyteArray bytes;
-#ifdef _AIX
- /* strerror() is not thread-safe on AIX so we have to use strerror_r() */
- char buffer[256];
- msg = (strerror_r((int)error, buffer, 256) == 0) ? buffer : "Error while calling strerror_r";
-#else
- msg = strerror((int)error);
-#endif
- len = strlen(msg);
+ getErrorString((int)errno, tmpbuf, sizeof(tmpbuf));
+ len = strlen(tmpbuf);
bytes = (*env)->NewByteArray(env, len);
if (bytes != NULL) {
- (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg);
+ (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)tmpbuf);
}
return bytes;
}
--- a/jdk/src/java.base/windows/native/libjava/jni_util_md.c Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/windows/native/libjava/jni_util_md.c Thu Oct 01 00:13:09 2015 +0100
@@ -108,13 +108,9 @@
}
} else if (errno != 0) {
// C runtime error that has no corresponding WIN32 error code
- const WCHAR *rtError = _wcserror(errno);
- if (rtError != NULL) {
- wcsncpy(utf16_osErrorMsg, rtError, cbErrorMsg);
- // truncate if too long
- utf16_osErrorMsg[cbErrorMsg - 1] = L'\0';
+ int ret = _wcserror_s(utf16_osErrorMsg, cbErrorMsg, errno);
+ if (ret == 0)
n = wcslen(utf16_osErrorMsg);
- }
} else
noError = TRUE; //OS has no error to report
@@ -147,3 +143,12 @@
}
return n;
}
+
+int
+getErrorString(int err, char *buf, size_t len)
+{
+ int ret = 0;
+ if (err == 0 || len < 1) return 0;
+ ret = strerror_s(buf, len, err);
+ return ret;
+}
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Thu Oct 01 00:09:51 2015 +0100
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Thu Oct 01 00:13:09 2015 +0100
@@ -2211,8 +2211,11 @@
optlen = sizeof(optval.i);
if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
- char errmsg[255];
- sprintf(errmsg, "error getting socket option: %s\n", strerror(errno));
+ char tmpbuf[255];
+ int size = 0;
+ char errmsg[255 + 31];
+ getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+ sprintf(errmsg, "error getting socket option: %s", tmpbuf);
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
return NULL;
}