Skip to content

Commit

Permalink
Merge pull request #1456 from matthiasblaesing/github-1452
Browse files Browse the repository at this point in the history
Allocate necessary memory to output full error message from native memory
  • Loading branch information
matthiasblaesing committed Aug 18, 2022
2 parents 927e5da + b1e90ac commit 0444bf9
Show file tree
Hide file tree
Showing 29 changed files with 69 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Features

Bug Fixes
---------
* [#1452](https://github.com/java-native-access/jna/issues/1452): Fix memory allocation/handling for error message generation in native library code (`dispatch.c`) - [@matthiasblaesing](https://github.com/matthiasblaesing).

Release 5.12.1
==============
Expand Down
2 changes: 1 addition & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
<!-- jnidispatch library release version -->
<property name="jni.major" value="6"/>
<property name="jni.minor" value="1"/>
<property name="jni.revision" value="4"/>
<property name="jni.revision" value="5"/>
<property name="jni.build" value="0"/> <!--${build.number}-->
<property name="jni.version" value="${jni.major}.${jni.minor}.${jni.revision}"/>
<property name="jni.md5" value="147a998f0cbc89681a1ae6c0dd121629"/>
Expand Down
Binary file modified lib/native/aix-ppc.jar
Binary file not shown.
Binary file modified lib/native/aix-ppc64.jar
Binary file not shown.
Binary file modified lib/native/darwin-aarch64.jar
Binary file not shown.
Binary file modified lib/native/darwin-x86-64.jar
Binary file not shown.
Binary file modified lib/native/freebsd-x86-64.jar
Binary file not shown.
Binary file modified lib/native/freebsd-x86.jar
Binary file not shown.
Binary file modified lib/native/linux-aarch64.jar
Binary file not shown.
Binary file modified lib/native/linux-arm.jar
Binary file not shown.
Binary file modified lib/native/linux-armel.jar
Binary file not shown.
Binary file modified lib/native/linux-loongarch64.jar
Binary file not shown.
Binary file modified lib/native/linux-mips64el.jar
Binary file not shown.
Binary file modified lib/native/linux-ppc.jar
Binary file not shown.
Binary file modified lib/native/linux-ppc64le.jar
Binary file not shown.
Binary file modified lib/native/linux-riscv64.jar
Binary file not shown.
Binary file modified lib/native/linux-s390x.jar
Binary file not shown.
Binary file modified lib/native/linux-x86-64.jar
Binary file not shown.
Binary file modified lib/native/linux-x86.jar
Binary file not shown.
Binary file modified lib/native/openbsd-x86-64.jar
Binary file not shown.
Binary file modified lib/native/openbsd-x86.jar
Binary file not shown.
Binary file modified lib/native/sunos-sparc.jar
Binary file not shown.
Binary file modified lib/native/sunos-sparcv9.jar
Binary file not shown.
Binary file modified lib/native/sunos-x86-64.jar
Binary file not shown.
Binary file modified lib/native/sunos-x86.jar
Binary file not shown.
Binary file modified lib/native/win32-aarch64.jar
Binary file not shown.
Binary file modified lib/native/win32-x86-64.jar
Binary file not shown.
Binary file modified lib/native/win32-x86.jar
Binary file not shown.
111 changes: 67 additions & 44 deletions native/dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "dispatch.h"

#include <string.h>
#include <stdlib.h>

#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
Expand All @@ -53,8 +54,8 @@
#define DEFAULT_LOAD_OPTS LOAD_WITH_ALTERED_SEARCH_PATH
#endif
#define LOAD_LIBRARY(NAME,OPTS) (NAME ? LoadLibraryExW(NAME, NULL, OPTS) : GetModuleHandleW(NULL))
#define LOAD_ERROR(BUF,LEN) w32_format_error(GetLastError(), BUF, LEN)
#define STR_ERROR(CODE,BUF,LEN) w32_format_error(CODE, BUF, LEN)
#define LOAD_ERROR() w32_format_error(GetLastError())
#define STR_ERROR(CODE) w32_format_error(CODE)
#define FREE_LIBRARY(HANDLE) (((HANDLE)==GetModuleHandleW(NULL) || FreeLibrary(HANDLE))?0:-1)
#define FIND_ENTRY(HANDLE, NAME) w32_find_entry(env, HANDLE, NAME)
#else
Expand All @@ -69,19 +70,32 @@
#endif
#define DEFAULT_LOAD_OPTS (RTLD_LAZY|RTLD_GLOBAL)
#define LOAD_LIBRARY(NAME,OPTS) dlopen(NAME, OPTS)
static inline char * LOAD_ERROR(char * buf, size_t len) {
const size_t count = snprintf(buf, len, "%s", dlerror());
assert(count <= len && "snprintf() output has been truncated");
static inline char * LOAD_ERROR() {
char* message = dlerror();
char* buf = (char*) malloc(strlen(message) + 1 /* null */);
strcpy(buf, message);
return buf;
}
static inline char * STR_ERROR(int code, char * buf, size_t len) {
// The conversion will fail if code is not a valid error code.
int err = strerror_r(code, buf, len);
if (err)
// Depending on glib version, "Unknown error" error code
// may be returned or passed using errno.
err = strerror_r(err > 0 ? err : errno, buf, len);
assert(err == 0 && "strerror_r() conversion has failed");
static inline char * STR_ERROR(int code) {
int i;
char* buf = NULL;
for(i = 256; i < (10 * 1024); i += 256) {
buf = (char*) malloc(i);
int res = strerror_r(code, buf, i);
if(res == 0) {
break;
}
free(buf);
buf = NULL;
if(res != ERANGE) {
break;
}
}
if(buf == NULL) {
int requiredBuffer = 25 /* static part*/ + 10 /* space for int */ + 1 /* null */;
buf = (char*) malloc(requiredBuffer);
snprintf(buf, requiredBuffer, "Failed to convert error: %d", code);
}
return buf;
}
#define FREE_LIBRARY(HANDLE) dlclose(HANDLE)
Expand Down Expand Up @@ -263,26 +277,23 @@ typedef void (JNICALL* release_t)(JNIEnv*,jarray,void*,jint);

#ifdef _WIN32
static char*
w32_format_error(int err, char* buf, int len) {
w32_format_error(int err) {
wchar_t* wbuf = NULL;
char* buf = NULL;
int wlen =
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_IGNORE_INSERTS
|FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, err, 0, (LPWSTR)&wbuf, 0, NULL);
if (wlen > 0) {
int result = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, len, NULL, NULL);
int bufSize = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL);
buf = (char*)malloc(bufSize);
int result = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, bufSize, NULL, NULL);
if (result == 0) {
fprintf(stderr, "JNA: error converting error message: %d\n", (int)GET_LAST_ERROR());
*buf = 0;
free(buf);
buf = NULL;
}
else {
buf[len-1] = 0;
}
}
else {
// Error retrieving message
*buf = 0;
}
if (wbuf) {
LocalFree(wbuf);
Expand All @@ -307,16 +318,18 @@ w32_short_name(JNIEnv* env, jstring str) {
wstr = wshort;
}
else {
char buf[MSG_SIZE];
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
char* buf = LOAD_ERROR();
throwByName(env, EError, buf);
free((void *)buf);
free((void *)wstr);
free((void *)wshort);
wstr = NULL;
}
}
else if (GET_LAST_ERROR() != ERROR_FILE_NOT_FOUND) {
char buf[MSG_SIZE];
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
char* buf = LOAD_ERROR();
throwByName(env, EError, buf);
free((void *)buf);
free((void *)wstr);
wstr = NULL;
}
Expand Down Expand Up @@ -680,8 +693,9 @@ dispatch(JNIEnv *env, void* func, jint flags, jobjectArray args,
int err = GET_LAST_ERROR();
JNA_set_last_error(env, err);
if ((flags & THROW_LAST_ERROR) && err) {
char emsg[MSG_SIZE - 3 /* literal characters */ - 10 /* max length of %d */];
snprintf(msg, sizeof(msg), "[%d] %s", err, STR_ERROR(err, emsg, sizeof(emsg)));
char* emsg = STR_ERROR(err);
snprintf(msg, MSG_SIZE, "[%d] %s", err, emsg);
free(emsg);
throw_type = ELastError;
throw_msg = msg;
}
Expand Down Expand Up @@ -1926,8 +1940,9 @@ dispatch_direct(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
int err = GET_LAST_ERROR();
JNA_set_last_error(env, err);
if (data->throw_last_error && err) {
char emsg[MSG_SIZE - 3 /* literal characters */ - 10 /* max length of %d */];
snprintf(msg, sizeof(msg), "[%d] %s", err, STR_ERROR(err, emsg, sizeof(emsg)));
char* emsg = STR_ERROR(err);
snprintf(msg, sizeof(msg), "[%d] %s", err, emsg);
free(emsg);
throw_type = ELastError;
throw_msg = msg;
}
Expand Down Expand Up @@ -2266,8 +2281,9 @@ Java_com_sun_jna_Native_open(JNIEnv *env, jclass UNUSED(cls), jstring lib, jint
}
#endif
if (!handle) {
char buf[MSG_SIZE];
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(buf, sizeof(buf)));
char* buf = LOAD_ERROR();
throwByName(env, EUnsatisfiedLink, buf);
free(buf);
}
if (libname != NULL) {
free((void *)libname);
Expand All @@ -2284,8 +2300,9 @@ JNIEXPORT void JNICALL
Java_com_sun_jna_Native_close(JNIEnv *env, jclass UNUSED(cls), jlong handle)
{
if (FREE_LIBRARY(L2A(handle))) {
char buf[MSG_SIZE];
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
char* buf = LOAD_ERROR();
throwByName(env, EError, buf);
free(buf);
}
}

Expand All @@ -2305,8 +2322,9 @@ Java_com_sun_jna_Native_findSymbol(JNIEnv *env, jclass UNUSED(cls),
if (funname != NULL) {
func = (void *)FIND_ENTRY(handle, funname);
if (!func) {
char buf[MSG_SIZE];
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(buf, sizeof(buf)));
char* buf = LOAD_ERROR();
throwByName(env, EUnsatisfiedLink, buf);
free(buf);
}
free((void *)funname);
}
Expand Down Expand Up @@ -3120,8 +3138,9 @@ Java_com_sun_jna_Native_getWindowHandle0(JNIEnv* UNUSED_JAWT(env), jclass UNUSED
free((void *)prop);
}
if ((jawt_handle = LOAD_LIBRARY(path, DEFAULT_LOAD_OPTS)) == NULL) {
char msg[MSG_SIZE];
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(msg, sizeof(msg)));
char* msg = LOAD_ERROR();
throwByName(env, EUnsatisfiedLink, msg);
free(msg);
return -1;
}
#else
Expand Down Expand Up @@ -3169,17 +3188,21 @@ Java_com_sun_jna_Native_getWindowHandle0(JNIEnv* UNUSED_JAWT(env), jclass UNUSED

if (jawt_handle == NULL) {
if ((jawt_handle = LOAD_LIBRARY(jawtLibraryName, DEFAULT_LOAD_OPTS)) == NULL) {
char msg[MSG_SIZE];
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(msg, sizeof(msg)));
char* msg = LOAD_ERROR();
throwByName(env, EUnsatisfiedLink, msg);
free(msg);
return -1;
}
}
#endif
if ((pJAWT_GetAWT = (void*)FIND_ENTRY(jawt_handle, METHOD_NAME)) == NULL) {
char msg[MSG_SIZE], buf[MSG_SIZE - 31 /* literal characters */ - sizeof(METHOD_NAME)];
snprintf(msg, sizeof(msg), "Error looking up JAWT method %s: %s",
METHOD_NAME, LOAD_ERROR(buf, sizeof(buf)));
char* buf = LOAD_ERROR();
size_t requiredBuffer = strlen(METHOD_NAME) + strlen(buf) + 31 /*static part*/ + 1 /*null*/;
char* msg = (char*) malloc(requiredBuffer);
snprintf(msg, requiredBuffer, "Error looking up JAWT method %s: %s", METHOD_NAME, buf);
throwByName(env, EUnsatisfiedLink, msg);
free(buf);
free(msg);
return -1;
}
}
Expand Down

0 comments on commit 0444bf9

Please sign in to comment.