Skip to content

Commit 0444bf9

Browse files
Merge pull request #1456 from matthiasblaesing/github-1452
Allocate necessary memory to output full error message from native memory
2 parents 927e5da + b1e90ac commit 0444bf9

29 files changed

+69
-45
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Features
1212

1313
Bug Fixes
1414
---------
15+
* [#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).
1516

1617
Release 5.12.1
1718
==============

build.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
<!-- jnidispatch library release version -->
7777
<property name="jni.major" value="6"/>
7878
<property name="jni.minor" value="1"/>
79-
<property name="jni.revision" value="4"/>
79+
<property name="jni.revision" value="5"/>
8080
<property name="jni.build" value="0"/> <!--${build.number}-->
8181
<property name="jni.version" value="${jni.major}.${jni.minor}.${jni.revision}"/>
8282
<property name="jni.md5" value="147a998f0cbc89681a1ae6c0dd121629"/>

lib/native/aix-ppc.jar

92 Bytes
Binary file not shown.

lib/native/aix-ppc64.jar

73 Bytes
Binary file not shown.

lib/native/darwin-aarch64.jar

0 Bytes
Binary file not shown.

lib/native/darwin-x86-64.jar

-107 Bytes
Binary file not shown.

lib/native/freebsd-x86-64.jar

-173 Bytes
Binary file not shown.

lib/native/freebsd-x86.jar

100 Bytes
Binary file not shown.

lib/native/linux-aarch64.jar

-111 Bytes
Binary file not shown.

lib/native/linux-arm.jar

-209 Bytes
Binary file not shown.

lib/native/linux-armel.jar

-217 Bytes
Binary file not shown.

lib/native/linux-loongarch64.jar

163 Bytes
Binary file not shown.

lib/native/linux-mips64el.jar

-97 Bytes
Binary file not shown.

lib/native/linux-ppc.jar

-96 Bytes
Binary file not shown.

lib/native/linux-ppc64le.jar

-30 Bytes
Binary file not shown.

lib/native/linux-riscv64.jar

-991 Bytes
Binary file not shown.

lib/native/linux-s390x.jar

90 Bytes
Binary file not shown.

lib/native/linux-x86-64.jar

-53 Bytes
Binary file not shown.

lib/native/linux-x86.jar

7 Bytes
Binary file not shown.

lib/native/openbsd-x86-64.jar

-114 Bytes
Binary file not shown.

lib/native/openbsd-x86.jar

-50 Bytes
Binary file not shown.

lib/native/sunos-sparc.jar

-136 Bytes
Binary file not shown.

lib/native/sunos-sparcv9.jar

-119 Bytes
Binary file not shown.

lib/native/sunos-x86-64.jar

64 Bytes
Binary file not shown.

lib/native/sunos-x86.jar

-76 Bytes
Binary file not shown.

lib/native/win32-aarch64.jar

-18 Bytes
Binary file not shown.

lib/native/win32-x86-64.jar

-16 Bytes
Binary file not shown.

lib/native/win32-x86.jar

-45 Bytes
Binary file not shown.

native/dispatch.c

Lines changed: 67 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "dispatch.h"
3131

3232
#include <string.h>
33+
#include <stdlib.h>
3334

3435
#if defined(_WIN32)
3536
#define WIN32_LEAN_AND_MEAN
@@ -53,8 +54,8 @@
5354
#define DEFAULT_LOAD_OPTS LOAD_WITH_ALTERED_SEARCH_PATH
5455
#endif
5556
#define LOAD_LIBRARY(NAME,OPTS) (NAME ? LoadLibraryExW(NAME, NULL, OPTS) : GetModuleHandleW(NULL))
56-
#define LOAD_ERROR(BUF,LEN) w32_format_error(GetLastError(), BUF, LEN)
57-
#define STR_ERROR(CODE,BUF,LEN) w32_format_error(CODE, BUF, LEN)
57+
#define LOAD_ERROR() w32_format_error(GetLastError())
58+
#define STR_ERROR(CODE) w32_format_error(CODE)
5859
#define FREE_LIBRARY(HANDLE) (((HANDLE)==GetModuleHandleW(NULL) || FreeLibrary(HANDLE))?0:-1)
5960
#define FIND_ENTRY(HANDLE, NAME) w32_find_entry(env, HANDLE, NAME)
6061
#else
@@ -69,19 +70,32 @@
6970
#endif
7071
#define DEFAULT_LOAD_OPTS (RTLD_LAZY|RTLD_GLOBAL)
7172
#define LOAD_LIBRARY(NAME,OPTS) dlopen(NAME, OPTS)
72-
static inline char * LOAD_ERROR(char * buf, size_t len) {
73-
const size_t count = snprintf(buf, len, "%s", dlerror());
74-
assert(count <= len && "snprintf() output has been truncated");
73+
static inline char * LOAD_ERROR() {
74+
char* message = dlerror();
75+
char* buf = (char*) malloc(strlen(message) + 1 /* null */);
76+
strcpy(buf, message);
7577
return buf;
7678
}
77-
static inline char * STR_ERROR(int code, char * buf, size_t len) {
78-
// The conversion will fail if code is not a valid error code.
79-
int err = strerror_r(code, buf, len);
80-
if (err)
81-
// Depending on glib version, "Unknown error" error code
82-
// may be returned or passed using errno.
83-
err = strerror_r(err > 0 ? err : errno, buf, len);
84-
assert(err == 0 && "strerror_r() conversion has failed");
79+
static inline char * STR_ERROR(int code) {
80+
int i;
81+
char* buf = NULL;
82+
for(i = 256; i < (10 * 1024); i += 256) {
83+
buf = (char*) malloc(i);
84+
int res = strerror_r(code, buf, i);
85+
if(res == 0) {
86+
break;
87+
}
88+
free(buf);
89+
buf = NULL;
90+
if(res != ERANGE) {
91+
break;
92+
}
93+
}
94+
if(buf == NULL) {
95+
int requiredBuffer = 25 /* static part*/ + 10 /* space for int */ + 1 /* null */;
96+
buf = (char*) malloc(requiredBuffer);
97+
snprintf(buf, requiredBuffer, "Failed to convert error: %d", code);
98+
}
8599
return buf;
86100
}
87101
#define FREE_LIBRARY(HANDLE) dlclose(HANDLE)
@@ -263,26 +277,23 @@ typedef void (JNICALL* release_t)(JNIEnv*,jarray,void*,jint);
263277

264278
#ifdef _WIN32
265279
static char*
266-
w32_format_error(int err, char* buf, int len) {
280+
w32_format_error(int err) {
267281
wchar_t* wbuf = NULL;
282+
char* buf = NULL;
268283
int wlen =
269284
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
270285
|FORMAT_MESSAGE_IGNORE_INSERTS
271286
|FORMAT_MESSAGE_ALLOCATE_BUFFER,
272287
NULL, err, 0, (LPWSTR)&wbuf, 0, NULL);
273288
if (wlen > 0) {
274-
int result = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, len, NULL, NULL);
289+
int bufSize = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL);
290+
buf = (char*)malloc(bufSize);
291+
int result = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, bufSize, NULL, NULL);
275292
if (result == 0) {
276293
fprintf(stderr, "JNA: error converting error message: %d\n", (int)GET_LAST_ERROR());
277-
*buf = 0;
294+
free(buf);
295+
buf = NULL;
278296
}
279-
else {
280-
buf[len-1] = 0;
281-
}
282-
}
283-
else {
284-
// Error retrieving message
285-
*buf = 0;
286297
}
287298
if (wbuf) {
288299
LocalFree(wbuf);
@@ -307,16 +318,18 @@ w32_short_name(JNIEnv* env, jstring str) {
307318
wstr = wshort;
308319
}
309320
else {
310-
char buf[MSG_SIZE];
311-
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
321+
char* buf = LOAD_ERROR();
322+
throwByName(env, EError, buf);
323+
free((void *)buf);
312324
free((void *)wstr);
313325
free((void *)wshort);
314326
wstr = NULL;
315327
}
316328
}
317329
else if (GET_LAST_ERROR() != ERROR_FILE_NOT_FOUND) {
318-
char buf[MSG_SIZE];
319-
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
330+
char* buf = LOAD_ERROR();
331+
throwByName(env, EError, buf);
332+
free((void *)buf);
320333
free((void *)wstr);
321334
wstr = NULL;
322335
}
@@ -680,8 +693,9 @@ dispatch(JNIEnv *env, void* func, jint flags, jobjectArray args,
680693
int err = GET_LAST_ERROR();
681694
JNA_set_last_error(env, err);
682695
if ((flags & THROW_LAST_ERROR) && err) {
683-
char emsg[MSG_SIZE - 3 /* literal characters */ - 10 /* max length of %d */];
684-
snprintf(msg, sizeof(msg), "[%d] %s", err, STR_ERROR(err, emsg, sizeof(emsg)));
696+
char* emsg = STR_ERROR(err);
697+
snprintf(msg, MSG_SIZE, "[%d] %s", err, emsg);
698+
free(emsg);
685699
throw_type = ELastError;
686700
throw_msg = msg;
687701
}
@@ -1926,8 +1940,9 @@ dispatch_direct(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
19261940
int err = GET_LAST_ERROR();
19271941
JNA_set_last_error(env, err);
19281942
if (data->throw_last_error && err) {
1929-
char emsg[MSG_SIZE - 3 /* literal characters */ - 10 /* max length of %d */];
1930-
snprintf(msg, sizeof(msg), "[%d] %s", err, STR_ERROR(err, emsg, sizeof(emsg)));
1943+
char* emsg = STR_ERROR(err);
1944+
snprintf(msg, sizeof(msg), "[%d] %s", err, emsg);
1945+
free(emsg);
19311946
throw_type = ELastError;
19321947
throw_msg = msg;
19331948
}
@@ -2266,8 +2281,9 @@ Java_com_sun_jna_Native_open(JNIEnv *env, jclass UNUSED(cls), jstring lib, jint
22662281
}
22672282
#endif
22682283
if (!handle) {
2269-
char buf[MSG_SIZE];
2270-
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(buf, sizeof(buf)));
2284+
char* buf = LOAD_ERROR();
2285+
throwByName(env, EUnsatisfiedLink, buf);
2286+
free(buf);
22712287
}
22722288
if (libname != NULL) {
22732289
free((void *)libname);
@@ -2284,8 +2300,9 @@ JNIEXPORT void JNICALL
22842300
Java_com_sun_jna_Native_close(JNIEnv *env, jclass UNUSED(cls), jlong handle)
22852301
{
22862302
if (FREE_LIBRARY(L2A(handle))) {
2287-
char buf[MSG_SIZE];
2288-
throwByName(env, EError, LOAD_ERROR(buf, sizeof(buf)));
2303+
char* buf = LOAD_ERROR();
2304+
throwByName(env, EError, buf);
2305+
free(buf);
22892306
}
22902307
}
22912308

@@ -2305,8 +2322,9 @@ Java_com_sun_jna_Native_findSymbol(JNIEnv *env, jclass UNUSED(cls),
23052322
if (funname != NULL) {
23062323
func = (void *)FIND_ENTRY(handle, funname);
23072324
if (!func) {
2308-
char buf[MSG_SIZE];
2309-
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(buf, sizeof(buf)));
2325+
char* buf = LOAD_ERROR();
2326+
throwByName(env, EUnsatisfiedLink, buf);
2327+
free(buf);
23102328
}
23112329
free((void *)funname);
23122330
}
@@ -3120,8 +3138,9 @@ Java_com_sun_jna_Native_getWindowHandle0(JNIEnv* UNUSED_JAWT(env), jclass UNUSED
31203138
free((void *)prop);
31213139
}
31223140
if ((jawt_handle = LOAD_LIBRARY(path, DEFAULT_LOAD_OPTS)) == NULL) {
3123-
char msg[MSG_SIZE];
3124-
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(msg, sizeof(msg)));
3141+
char* msg = LOAD_ERROR();
3142+
throwByName(env, EUnsatisfiedLink, msg);
3143+
free(msg);
31253144
return -1;
31263145
}
31273146
#else
@@ -3169,17 +3188,21 @@ Java_com_sun_jna_Native_getWindowHandle0(JNIEnv* UNUSED_JAWT(env), jclass UNUSED
31693188

31703189
if (jawt_handle == NULL) {
31713190
if ((jawt_handle = LOAD_LIBRARY(jawtLibraryName, DEFAULT_LOAD_OPTS)) == NULL) {
3172-
char msg[MSG_SIZE];
3173-
throwByName(env, EUnsatisfiedLink, LOAD_ERROR(msg, sizeof(msg)));
3191+
char* msg = LOAD_ERROR();
3192+
throwByName(env, EUnsatisfiedLink, msg);
3193+
free(msg);
31743194
return -1;
31753195
}
31763196
}
31773197
#endif
31783198
if ((pJAWT_GetAWT = (void*)FIND_ENTRY(jawt_handle, METHOD_NAME)) == NULL) {
3179-
char msg[MSG_SIZE], buf[MSG_SIZE - 31 /* literal characters */ - sizeof(METHOD_NAME)];
3180-
snprintf(msg, sizeof(msg), "Error looking up JAWT method %s: %s",
3181-
METHOD_NAME, LOAD_ERROR(buf, sizeof(buf)));
3199+
char* buf = LOAD_ERROR();
3200+
size_t requiredBuffer = strlen(METHOD_NAME) + strlen(buf) + 31 /*static part*/ + 1 /*null*/;
3201+
char* msg = (char*) malloc(requiredBuffer);
3202+
snprintf(msg, requiredBuffer, "Error looking up JAWT method %s: %s", METHOD_NAME, buf);
31823203
throwByName(env, EUnsatisfiedLink, msg);
3204+
free(buf);
3205+
free(msg);
31833206
return -1;
31843207
}
31853208
}

0 commit comments

Comments
 (0)