From c46af75d747eabce30dd6feac437b9fc39b01d31 Mon Sep 17 00:00:00 2001 From: Doug MacEachern Date: Thu, 15 Apr 2010 10:55:09 -0700 Subject: [PATCH] (SIGAR-201) JNIEnv->ExceptionCheck to avoid possible SEGV on OutOfMemoryError --- bindings/java/src/jni/javasigar.c | 47 +++++++++++++++++---- bindings/java/src/jni/javasigar.h | 3 ++ bindings/java/src/jni/win32/eventlog.c | 5 ++- bindings/java/src/jni/win32/metabase.cpp | 8 +++- bindings/java/src/jni/win32/pdh.c | 24 +++++++++++ bindings/java/src/jni/win32/registrykey.cpp | 5 ++- bindings/java/src/jni/win32/service.cpp | 26 +++++++++++- 7 files changed, 103 insertions(+), 15 deletions(-) diff --git a/bindings/java/src/jni/javasigar.c b/bindings/java/src/jni/javasigar.c index 138c1497..b0be9428 100644 --- a/bindings/java/src/jni/javasigar.c +++ b/bindings/java/src/jni/javasigar.c @@ -249,7 +249,7 @@ int jsigar_list_init(JNIEnv *env, jsigar_list_t *obj) obj->obj = JENV->NewObject(env, listclass, listid); obj->id = addid; - return SIGAR_OK; + return JENV->ExceptionCheck(env) ? !SIGAR_OK : SIGAR_OK; } int jsigar_list_add(void *data, char *value, int len) @@ -260,7 +260,7 @@ int jsigar_list_add(void *data, char *value, int len) JENV->CallBooleanMethod(env, obj->obj, obj->id, JENV->NewStringUTF(env, value)); - return SIGAR_OK; + return JENV->ExceptionCheck(env) ? !SIGAR_OK : SIGAR_OK; } JNIEXPORT jstring SIGAR_JNIx(formatSize) @@ -398,9 +398,6 @@ static jstring jnet_address_to_string(JNIEnv *env, sigar_t *sigar, sigar_net_add #include "javasigar_generated.c" -#define SIGAR_ALLOC_OBJECT(name) \ - JENV->AllocObject(env, SIGAR_FIND_CLASS(name)) - enum { FS_FIELD_DIRNAME, FS_FIELD_DEVNAME, @@ -448,6 +445,7 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getFileSystemListNative) JENV->GetFieldID(env, cls, "type", "I"); fsarray = JENV->NewObjectArray(env, fslist.number, cls, 0); + SIGAR_CHEX; for (i=0; iAllocObject(env, obj_cls); + SIGAR_CHEX; JENV->SetStringField(env, fsobj, ids[FS_FIELD_DIRNAME], @@ -498,6 +497,7 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getFileSystemListNative) fs->type); JENV->SetObjectArrayElement(env, fsarray, i, fsobj); + SIGAR_CHEX; } sigar_file_system_list_destroy(sigar, &fslist); @@ -562,12 +562,15 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getCpuInfoList) JAVA_SIGAR_INIT_FIELDS_CPUINFO(cls); cpuarray = JENV->NewObjectArray(env, cpu_infos.number, cls, 0); + SIGAR_CHEX; for (i=0; iAllocObject(env, cls); + SIGAR_CHEX; JAVA_SIGAR_SET_FIELDS_CPUINFO(cls, info_obj, cpu_infos.data[i]); JENV->SetObjectArrayElement(env, cpuarray, i, info_obj); + SIGAR_CHEX; } sigar_cpu_info_list_destroy(sigar, &cpu_infos); @@ -593,12 +596,15 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getCpuListNative) JAVA_SIGAR_INIT_FIELDS_CPU(cls); cpuarray = JENV->NewObjectArray(env, cpulist.number, cls, 0); + SIGAR_CHEX; for (i=0; iAllocObject(env, cls); + SIGAR_CHEX; JAVA_SIGAR_SET_FIELDS_CPU(cls, info_obj, cpulist.data[i]); JENV->SetObjectArrayElement(env, cpuarray, i, info_obj); + SIGAR_CHEX; } sigar_cpu_list_destroy(sigar, &cpulist); @@ -635,6 +641,7 @@ JNIEXPORT jlongArray SIGAR_JNIx(getProcList) } procarray = JENV->NewLongArray(env, proclist.number); + SIGAR_CHEX; if (sizeof(jlong) == sizeof(sigar_pid_t)) { pids = (jlong *)proclist.data; @@ -676,10 +683,12 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getProcArgs) } argsarray = JENV->NewObjectArray(env, procargs.number, stringclass, 0); + SIGAR_CHEX; for (i=0; iNewStringUTF(env, procargs.data[i]); JENV->SetObjectArrayElement(env, argsarray, i, s); + SIGAR_CHEX; } sigar_proc_args_destroy(sigar, &procargs); @@ -704,7 +713,7 @@ static int jni_env_getall(void *data, JENV->NewStringUTF(env, key), JENV->NewStringUTF(env, val)); - return SIGAR_OK; + return JENV->ExceptionCheck(env) ? !SIGAR_OK : SIGAR_OK; } #define MAP_PUT_SIG \ @@ -728,6 +737,7 @@ JNIEXPORT jobject SIGAR_JNI(ProcEnv_getAll) dSIGAR(NULL); hashmap = JENV->NewObject(env, mapclass, mapid); + SIGAR_CHEX; put.env = env; put.id = putid; @@ -809,7 +819,9 @@ JNIEXPORT jobject SIGAR_JNIx(getProcModulesNative) dSIGAR(NULL); - jsigar_list_init(env, &obj); + if (jsigar_list_init(env, &obj) != SIGAR_OK) { + return NULL; /* Exception thrown */ + } procmods.module_getter = jsigar_list_add; procmods.data = &obj; @@ -837,6 +849,7 @@ JNIEXPORT jdoubleArray SIGAR_JNIx(getLoadAverage) } avgarray = JENV->NewDoubleArray(env, 3); + SIGAR_CHEX; JENV->SetDoubleArrayRegion(env, avgarray, 0, 3, loadavg.loadavg); @@ -862,11 +875,14 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getNetRouteList) JAVA_SIGAR_INIT_FIELDS_NETROUTE(cls); routearray = JENV->NewObjectArray(env, routelist.number, cls, 0); + SIGAR_CHEX; for (i=0; iAllocObject(env, cls); + SIGAR_CHEX; JAVA_SIGAR_SET_FIELDS_NETROUTE(cls, obj, routelist.data[i]); JENV->SetObjectArrayElement(env, routearray, i, obj); + SIGAR_CHEX; } sigar_net_route_list_destroy(sigar, &routelist); @@ -902,11 +918,14 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getNetConnectionList) JAVA_SIGAR_INIT_FIELDS_NETCONNECTION(cls); connarray = JENV->NewObjectArray(env, connlist.number, cls, 0); + SIGAR_CHEX; for (i=0; iAllocObject(env, cls); + SIGAR_CHEX; JAVA_SIGAR_SET_FIELDS_NETCONNECTION(cls, obj, connlist.data[i]); JENV->SetObjectArrayElement(env, connarray, i, obj); + SIGAR_CHEX; } sigar_net_connection_list_destroy(sigar, &connlist); @@ -983,6 +1002,10 @@ JNIEXPORT void SIGAR_JNI(NetStat_stat) } states = JENV->NewIntArray(env, SIGAR_TCP_UNKNOWN); + if (JENV->ExceptionCheck(env)) { + return; + } + JENV->SetIntArrayRegion(env, states, 0, SIGAR_TCP_UNKNOWN, tcp_states); @@ -1056,12 +1079,15 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getWhoList) JAVA_SIGAR_INIT_FIELDS_WHO(cls); whoarray = JENV->NewObjectArray(env, wholist.number, cls, 0); + SIGAR_CHEX; for (i=0; iAllocObject(env, cls); + SIGAR_CHEX; JAVA_SIGAR_SET_FIELDS_WHO(cls, info_obj, wholist.data[i]); JENV->SetObjectArrayElement(env, whoarray, i, info_obj); + SIGAR_CHEX; } sigar_who_list_destroy(sigar, &wholist); @@ -1158,10 +1184,12 @@ JNIEXPORT jobjectArray SIGAR_JNIx(getNetInterfaceList) } ifarray = JENV->NewObjectArray(env, iflist.number, stringclass, 0); + SIGAR_CHEX; for (i=0; iNewStringUTF(env, iflist.data[i]); JENV->SetObjectArrayElement(env, ifarray, i, s); + SIGAR_CHEX; } sigar_net_interface_list_destroy(sigar, &iflist); @@ -1355,6 +1383,7 @@ JNIEXPORT jlongArray SIGAR_JNI(ptql_SigarProcessQuery_find) } procarray = JENV->NewLongArray(env, proclist.number); + SIGAR_CHEX; if (sizeof(jlong) == sizeof(sigar_pid_t)) { pids = (jlong *)proclist.data; @@ -1466,7 +1495,7 @@ static int jsigar_getline_completer(char *buffer, int offset, int *pos) JENV->CallObjectMethod(env, jsigar_completer.obj, jsigar_completer.id, jbuffer); - if (JENV->ExceptionOccurred(env)) { + if (JENV->ExceptionCheck(env)) { JENV->ExceptionDescribe(env); return 0; } @@ -1547,7 +1576,7 @@ static void jsigar_log_impl(sigar_t *sigar, void *data, log_methods[level], "(Ljava/lang/Object;)V"); - if (JENV->ExceptionOccurred(env)) { + if (JENV->ExceptionCheck(env)) { JENV->ExceptionDescribe(env); return; } diff --git a/bindings/java/src/jni/javasigar.h b/bindings/java/src/jni/javasigar.h index a3415610..6b0ea30b 100644 --- a/bindings/java/src/jni/javasigar.h +++ b/bindings/java/src/jni/javasigar.h @@ -33,6 +33,9 @@ #define SIGAR_CLASS_SIG(name) \ "L" SIGAR_PACKAGE name ";" +/* CHeck EXception */ +#define SIGAR_CHEX if (JENV->ExceptionCheck(env)) return NULL + typedef struct { JNIEnv *env; jobject obj; diff --git a/bindings/java/src/jni/win32/eventlog.c b/bindings/java/src/jni/win32/eventlog.c index 011e37f3..452e2c18 100644 --- a/bindings/java/src/jni/win32/eventlog.c +++ b/bindings/java/src/jni/win32/eventlog.c @@ -294,6 +294,7 @@ JNIEXPORT jobject SIGAR_JNI(win32_EventLog_readlog) } obj = JENV->AllocObject(env, cls); + SIGAR_CHEX; id = JENV->GetFieldID(env, cls, "recordNumber", "J"); JENV->SetLongField(env, obj, id, pevlr->RecordNumber); @@ -310,9 +311,9 @@ JNIEXPORT jobject SIGAR_JNI(win32_EventLog_readlog) id = JENV->GetFieldID(env, cls, "eventType", "S"); JENV->SetShortField(env, obj, id, pevlr->EventType); - if (!JENV->ExceptionOccurred(env)) { /* careful not to clear any existing exception */ + if (!JENV->ExceptionCheck(env)) { /* careful not to clear any existing exception */ id = JENV->GetFieldID(env, cls, "category", "S"); - if (JENV->ExceptionOccurred(env)) { + if (JENV->ExceptionCheck(env)) { /* older version of sigar.jar being used with sigar.dll */ JENV->ExceptionClear(env); } diff --git a/bindings/java/src/jni/win32/metabase.cpp b/bindings/java/src/jni/win32/metabase.cpp index 0cace464..d505e65b 100644 --- a/bindings/java/src/jni/win32/metabase.cpp +++ b/bindings/java/src/jni/win32/metabase.cpp @@ -269,7 +269,10 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_MetaBase_MetaBaseGetMultiStringValue) NewObjectArray(count, env->FindClass("java/lang/String"), env->NewString((const jchar *)"", 1)); - + if (env->ExceptionCheck()) { + return NULL; + } + // Walk the return instance list, creating an array for (szThisInstance = (TCHAR *)MyRecord.pbMDData, i = 0; *szThisInstance != 0; @@ -278,6 +281,9 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_MetaBase_MetaBaseGetMultiStringValue) env->SetObjectArrayElement(ret,i,env->NewString( (const jchar *)(LPCTSTR)szThisInstance, lstrlen(szThisInstance))); + if (env->ExceptionCheck()) { + return NULL; + } } return ret; } diff --git a/bindings/java/src/jni/win32/pdh.c b/bindings/java/src/jni/win32/pdh.c index a5aefe67..acdd2c95 100644 --- a/bindings/java/src/jni/win32/pdh.c +++ b/bindings/java/src/jni/win32/pdh.c @@ -319,6 +319,10 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetInstances) JENV->FindClass(env, "java/lang/String"), JENV->NewStringUTF(env, "")); + if (JENV->ExceptionCheck(env)) { + free(instance_list_buf); + return NULL; + } /* Walk the return instance list, creating an array */ for (cur_object = instance_list_buf, i = 0; @@ -329,6 +333,10 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetInstances) jstring s = JENV->NewString(env, (const jchar *)cur_object, len); JENV->SetObjectArrayElement(env, array, i, s); + if (JENV->ExceptionCheck(env)) { + free(instance_list_buf); + return NULL; + } cur_object += len + 1; } } else { @@ -391,6 +399,10 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetKeys) JENV->FindClass(env, "java/lang/String"), JENV->NewStringUTF(env, "")); + if (JENV->ExceptionCheck(env)) { + free(instance_list_buf); + return NULL; + } /* Walk the return instance list, creating an array */ for (cur_object = instance_list_buf, i = 0; @@ -401,6 +413,10 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetKeys) jstring s = JENV->NewString(env, (const jchar *)cur_object, len); JENV->SetObjectArrayElement(env, array, i, s); + if (JENV->ExceptionCheck(env)) { + free(instance_list_buf); + return NULL; + } cur_object += len + 1; } } else { @@ -459,6 +475,10 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetObjects) JENV->FindClass(env, "java/lang/String"), JENV->NewStringUTF(env, "")); + if (JENV->ExceptionCheck(env)) { + free(list_buf); + return NULL; + } for (cur_object = list_buf, i = 0; *cur_object != 0; @@ -468,6 +488,10 @@ JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetObjects) jstring s = JENV->NewString(env, (const jchar *)cur_object, len); JENV->SetObjectArrayElement(env, array, i, s); + if (JENV->ExceptionCheck(env)) { + free(list_buf); + return NULL; + } cur_object += len + 1; } diff --git a/bindings/java/src/jni/win32/registrykey.cpp b/bindings/java/src/jni/win32/registrykey.cpp index 2995c3dc..52c491bf 100755 --- a/bindings/java/src/jni/win32/registrykey.cpp +++ b/bindings/java/src/jni/win32/registrykey.cpp @@ -331,7 +331,10 @@ JNIEXPORT void SIGAR_JNI(win32_RegistryKey_RegQueryMultiStringValue) env->NewString((const jchar *)ptr, len); env->CallBooleanMethod(obj, id, jval); - + if (env->ExceptionCheck()) { + HeapFree(GetProcessHeap(), 0, value); + return; + } ptr += len + 1; } } diff --git a/bindings/java/src/jni/win32/service.cpp b/bindings/java/src/jni/win32/service.cpp index eaffb85a..6fa66c8d 100644 --- a/bindings/java/src/jni/win32/service.cpp +++ b/bindings/java/src/jni/win32/service.cpp @@ -289,6 +289,9 @@ static int to_array(JNIEnv *env, LPTSTR str, jobjectArray array) jstring jstr = env->NewString((const jchar *)ptr, slen); env->SetObjectArrayElement(array, i, jstr); + if (env->ExceptionCheck()) { + return -1; + } } offset += slen + 1; ptr = &str[offset]; @@ -333,11 +336,19 @@ JNIEXPORT jboolean SIGAR_JNI(win32_Service_QueryServiceConfig) int i; jobjectArray jargv = env->NewObjectArray(argc, stringclass, 0); + if (env->ExceptionCheck()) { + LocalFree(argv); + return JNI_FALSE; + } for (i=0; iNewString((const jchar *)argv[i], lstrlen(argv[i])); env->SetObjectArrayElement(jargv, i, jstr); + if (env->ExceptionCheck()) { + LocalFree(argv); + return JNI_FALSE; + } } id = env->GetFieldID(cls, "argv", ASTRING_SIG); @@ -352,11 +363,22 @@ JNIEXPORT jboolean SIGAR_JNI(win32_Service_QueryServiceConfig) if (config->lpDependencies) { /* first pass just get num for NewObjectArray */ + jobjectArray dependencies; int num = to_array(env, config->lpDependencies, NULL); - jobjectArray dependencies = - env->NewObjectArray(num, stringclass, 0); + + if (num < 0) { + return JNI_FALSE; /* Exception thrown */ + } + + dependencies = env->NewObjectArray(num, stringclass, 0); + if (env->ExceptionCheck()) { + return JNI_FALSE; + } to_array(env, config->lpDependencies, dependencies); + if (num < 0) { + return JNI_FALSE; /* Exception thrown */ + } id = env->GetFieldID(cls, "dependencies", ASTRING_SIG);