8133249: Occasional SIGSEGV: non thread-safe use of strerr in getLastErrorString
Reviewed-by: igerasim, rriggs, christos
This commit is contained in:
parent
ddf365ac99
commit
7127fab647
@ -160,6 +160,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
|
|||||||
-framework Security -framework SystemConfiguration, \
|
-framework Security -framework SystemConfiguration, \
|
||||||
LDFLAGS_SUFFIX_windows := -export:winFileHandleOpen -export:handleLseek \
|
LDFLAGS_SUFFIX_windows := -export:winFileHandleOpen -export:handleLseek \
|
||||||
-export:getLastErrorString \
|
-export:getLastErrorString \
|
||||||
|
-export:getErrorString \
|
||||||
jvm.lib $(BUILD_LIBFDLIBM) $(WIN_VERIFY_LIB) \
|
jvm.lib $(BUILD_LIBFDLIBM) $(WIN_VERIFY_LIB) \
|
||||||
shell32.lib delayimp.lib -DELAYLOAD:shell32.dll \
|
shell32.lib delayimp.lib -DELAYLOAD:shell32.dll \
|
||||||
advapi32.lib version.lib, \
|
advapi32.lib version.lib, \
|
||||||
|
@ -282,8 +282,9 @@ SUNWprivate_1.1 {
|
|||||||
|
|
||||||
# ZipFile.c needs this one
|
# ZipFile.c needs this one
|
||||||
throwFileNotFoundException;
|
throwFileNotFoundException;
|
||||||
# zip_util.c needs this one
|
# zip_util.c needs these
|
||||||
getLastErrorString;
|
getLastErrorString;
|
||||||
|
getErrorString;
|
||||||
|
|
||||||
# Outcalls from libjvm done using dlsym().
|
# Outcalls from libjvm done using dlsym().
|
||||||
|
|
||||||
|
@ -388,6 +388,7 @@ void buildJniFunctionName(const char *sym, const char *cname,
|
|||||||
char *jniEntryName);
|
char *jniEntryName);
|
||||||
|
|
||||||
extern size_t getLastErrorString(char *buf, size_t len);
|
extern size_t getLastErrorString(char *buf, size_t len);
|
||||||
|
extern int getErrorString(int err, char *buf, size_t len);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@ -1438,6 +1438,7 @@ jboolean JNICALL
|
|||||||
ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
|
ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
|
||||||
{
|
{
|
||||||
char *msg;
|
char *msg;
|
||||||
|
char tmpbuf[1024];
|
||||||
|
|
||||||
strcpy(entryname, entry->name);
|
strcpy(entryname, entry->name);
|
||||||
if (entry->csize == 0) {
|
if (entry->csize == 0) {
|
||||||
@ -1456,8 +1457,11 @@ ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
|
|||||||
msg = zip->msg;
|
msg = zip->msg;
|
||||||
ZIP_Unlock(zip);
|
ZIP_Unlock(zip);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
jio_fprintf(stderr, "%s: %s\n", zip->name,
|
if (msg == 0) {
|
||||||
msg != 0 ? msg : strerror(errno));
|
getErrorString(errno, tmpbuf, sizeof(tmpbuf));
|
||||||
|
msg = tmpbuf;
|
||||||
|
}
|
||||||
|
jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
buf += n;
|
buf += n;
|
||||||
@ -1470,8 +1474,11 @@ ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
|
|||||||
if ((msg == NULL) || (*msg == 0)) {
|
if ((msg == NULL) || (*msg == 0)) {
|
||||||
msg = zip->msg;
|
msg = zip->msg;
|
||||||
}
|
}
|
||||||
jio_fprintf(stderr, "%s: %s\n", zip->name,
|
if (msg == 0) {
|
||||||
msg != 0 ? msg : strerror(errno));
|
getErrorString(errno, tmpbuf, sizeof(tmpbuf));
|
||||||
|
msg = tmpbuf;
|
||||||
|
}
|
||||||
|
jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,12 +248,13 @@ throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
|
|||||||
const char *detail = defaultDetail;
|
const char *detail = defaultDetail;
|
||||||
char *errmsg;
|
char *errmsg;
|
||||||
size_t fmtsize;
|
size_t fmtsize;
|
||||||
|
char tmpbuf[1024];
|
||||||
jstring s;
|
jstring s;
|
||||||
|
|
||||||
if (errnum != 0) {
|
if (errnum != 0) {
|
||||||
const char *s = strerror(errnum);
|
int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf));
|
||||||
if (strcmp(s, "Unknown error") != 0)
|
if (ret != EINVAL)
|
||||||
detail = s;
|
detail = tmpbuf;
|
||||||
}
|
}
|
||||||
/* ASCII Decimal representation uses 2.4 times as many bits as binary. */
|
/* ASCII Decimal representation uses 2.4 times as many bits as binary. */
|
||||||
fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum);
|
fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum);
|
||||||
|
@ -30,6 +30,13 @@
|
|||||||
#include "jni_util.h"
|
#include "jni_util.h"
|
||||||
#include "dlfcn.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() {
|
void* getProcessHandle() {
|
||||||
static void *procHandle = NULL;
|
static void *procHandle = NULL;
|
||||||
if (procHandle != NULL) {
|
if (procHandle != NULL) {
|
||||||
@ -55,16 +62,14 @@ void buildJniFunctionName(const char *sym, const char *cname,
|
|||||||
size_t
|
size_t
|
||||||
getLastErrorString(char *buf, size_t len)
|
getLastErrorString(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
char *err;
|
|
||||||
size_t n;
|
|
||||||
if (errno == 0 || len < 1) return 0;
|
if (errno == 0 || len < 1) return 0;
|
||||||
|
getErrorString(errno, buf, len);
|
||||||
err = strerror(errno);
|
return strlen(buf);
|
||||||
n = strlen(err);
|
}
|
||||||
if (n >= len)
|
|
||||||
n = len - 1;
|
int
|
||||||
|
getErrorString(int err, char *buf, size_t len)
|
||||||
strncpy(buf, err, n);
|
{
|
||||||
buf[n] = '\0';
|
if (err == 0 || len < 1) return 0;
|
||||||
return n;
|
return strerror_r(err, buf, len);
|
||||||
}
|
}
|
||||||
|
@ -918,6 +918,7 @@ Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
|
|||||||
jobject this) {
|
jobject this) {
|
||||||
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
|
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
|
||||||
int arg, fd, t = 1;
|
int arg, fd, t = 1;
|
||||||
|
char tmpbuf[1024];
|
||||||
#ifdef AF_INET6
|
#ifdef AF_INET6
|
||||||
int domain = ipv6_available() ? AF_INET6 : AF_INET;
|
int domain = ipv6_available() ? AF_INET6 : AF_INET;
|
||||||
#else
|
#else
|
||||||
@ -953,22 +954,23 @@ Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
|
|||||||
arg = 65507;
|
arg = 65507;
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
|
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
|
||||||
(char *)&arg, sizeof(arg)) < 0) {
|
(char *)&arg, sizeof(arg)) < 0) {
|
||||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
getErrorString(errno, tmpbuf, sizeof(tmpbuf));
|
||||||
strerror(errno));
|
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
|
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
|
||||||
(char *)&arg, sizeof(arg)) < 0) {
|
(char *)&arg, sizeof(arg)) < 0) {
|
||||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
getErrorString(errno, tmpbuf, sizeof(tmpbuf));
|
||||||
strerror(errno));
|
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* __APPLE__ */
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof (int)) < 0) {
|
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);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -977,9 +979,10 @@ Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
|
|||||||
arg = 0;
|
arg = 0;
|
||||||
int level = (domain == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
|
int level = (domain == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
|
||||||
if ((setsockopt(fd, level, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&
|
if ((setsockopt(fd, level, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&
|
||||||
(errno != ENOPROTOOPT)) {
|
(errno != ENOPROTOOPT))
|
||||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
{
|
||||||
strerror(errno));
|
getErrorString(errno, tmpbuf, sizeof(tmpbuf));
|
||||||
|
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -994,7 +997,8 @@ Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
|
|||||||
int ttl = 1;
|
int ttl = 1;
|
||||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &ttl,
|
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &ttl,
|
||||||
sizeof (ttl)) < 0) {
|
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);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -315,21 +315,15 @@ Java_sun_nio_fs_UnixNativeDispatcher_getcwd(JNIEnv* env, jclass this) {
|
|||||||
JNIEXPORT jbyteArray
|
JNIEXPORT jbyteArray
|
||||||
Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
|
Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
|
||||||
{
|
{
|
||||||
char* msg;
|
char tmpbuf[1024];
|
||||||
jsize len;
|
jsize len;
|
||||||
jbyteArray bytes;
|
jbyteArray bytes;
|
||||||
|
|
||||||
#ifdef _AIX
|
getErrorString((int)errno, tmpbuf, sizeof(tmpbuf));
|
||||||
/* strerror() is not thread-safe on AIX so we have to use strerror_r() */
|
len = strlen(tmpbuf);
|
||||||
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);
|
|
||||||
bytes = (*env)->NewByteArray(env, len);
|
bytes = (*env)->NewByteArray(env, len);
|
||||||
if (bytes != NULL) {
|
if (bytes != NULL) {
|
||||||
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg);
|
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)tmpbuf);
|
||||||
}
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
@ -108,13 +108,9 @@ getLastErrorString(char *utf8_jvmErrorMsg, size_t cbErrorMsg)
|
|||||||
}
|
}
|
||||||
} else if (errno != 0) {
|
} else if (errno != 0) {
|
||||||
// C runtime error that has no corresponding WIN32 error code
|
// C runtime error that has no corresponding WIN32 error code
|
||||||
const WCHAR *rtError = _wcserror(errno);
|
int ret = _wcserror_s(utf16_osErrorMsg, cbErrorMsg, errno);
|
||||||
if (rtError != NULL) {
|
if (ret == 0)
|
||||||
wcsncpy(utf16_osErrorMsg, rtError, cbErrorMsg);
|
|
||||||
// truncate if too long
|
|
||||||
utf16_osErrorMsg[cbErrorMsg - 1] = L'\0';
|
|
||||||
n = wcslen(utf16_osErrorMsg);
|
n = wcslen(utf16_osErrorMsg);
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
noError = TRUE; //OS has no error to report
|
noError = TRUE; //OS has no error to report
|
||||||
|
|
||||||
@ -147,3 +143,12 @@ getLastErrorString(char *utf8_jvmErrorMsg, size_t cbErrorMsg)
|
|||||||
}
|
}
|
||||||
return n;
|
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;
|
||||||
|
}
|
||||||
|
@ -2211,8 +2211,11 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobj
|
|||||||
|
|
||||||
optlen = sizeof(optval.i);
|
optlen = sizeof(optval.i);
|
||||||
if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
|
if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
|
||||||
char errmsg[255];
|
char tmpbuf[255];
|
||||||
sprintf(errmsg, "error getting socket option: %s\n", strerror(errno));
|
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);
|
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user