From b4920dd6d8afa729a8c4324c434bad53df68f75f Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 2 Feb 2021 17:57:58 -0500 Subject: [PATCH] Fix some memory leaks and an iterator use after free --- src/main/native/CLJNIUtils.cpp | 30 ++++++++++++++++++------------ src/main/native/ConversionsCL.cpp | 2 +- src/main/native/ConversionsCL.hpp | 5 +++-- src/main/native/JNIUtils.cpp | 10 ++++++---- src/main/native/PointerUtils.cpp | 8 ++++++-- 5 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/main/native/CLJNIUtils.cpp b/src/main/native/CLJNIUtils.cpp index f49d574..b4572f2 100644 --- a/src/main/native/CLJNIUtils.cpp +++ b/src/main/native/CLJNIUtils.cpp @@ -183,7 +183,7 @@ cl_context_properties* createContextPropertiesArray(JNIEnv *env, jobject propert } javaPropertiesSize++; } - cl_context_properties *nativeProperties = new cl_context_properties[javaPropertiesSize + 1]; + cl_context_properties *nativeProperties = new (std::nothrow) cl_context_properties[javaPropertiesSize + 1]; if (nativeProperties == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -232,7 +232,7 @@ cl_queue_properties* createQueuePropertiesArray(JNIEnv *env, jobject properties) } javaPropertiesSize++; } - cl_queue_properties *nativeProperties = new cl_queue_properties[javaPropertiesSize + 1]; + cl_queue_properties *nativeProperties = new (std::nothrow) cl_queue_properties[javaPropertiesSize + 1]; if (nativeProperties == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -280,7 +280,7 @@ cl_pipe_properties* createPipePropertiesArray(JNIEnv *env, jobject properties) } javaPropertiesSize++; } - cl_pipe_properties *nativeProperties = new cl_pipe_properties[javaPropertiesSize + 1]; + cl_pipe_properties *nativeProperties = new (std::nothrow) cl_pipe_properties[javaPropertiesSize + 1]; if (nativeProperties == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -328,7 +328,7 @@ cl_sampler_properties* createSamplerPropertiesArray(JNIEnv *env, jobject propert } javaPropertiesSize++; } - cl_sampler_properties *nativeProperties = new cl_sampler_properties[javaPropertiesSize + 1]; + cl_sampler_properties *nativeProperties = new (std::nothrow) cl_sampler_properties[javaPropertiesSize + 1]; if (nativeProperties == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -454,7 +454,7 @@ cl_device_partition_property* getCl_device_partition_property (JNIEnv *env, jobj } javaPropertiesSize++; } - cl_device_partition_property *nativeProperties = new cl_device_partition_property[javaPropertiesSize + 1]; + cl_device_partition_property *nativeProperties = new (std::nothrow) cl_device_partition_property[javaPropertiesSize + 1]; if (nativeProperties == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -485,7 +485,7 @@ cl_device_partition_property* getCl_device_partition_property (JNIEnv *env, jobj */ cl_event* createEventList(JNIEnv *env, jobjectArray event_list, cl_uint num_events) { - cl_event* nativeEvent_list = new cl_event[num_events]; + cl_event* nativeEvent_list = new (std::nothrow) cl_event[num_events]; if (nativeEvent_list == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -496,6 +496,7 @@ cl_event* createEventList(JNIEnv *env, jobjectArray event_list, cl_uint num_even cl_uint event_listLength = (cl_uint)env->GetArrayLength(event_list); if (event_listLength < num_events) { + delete[] nativeEvent_list; ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", "Event list size is smaller than specified number of events"); return NULL; @@ -533,7 +534,7 @@ cl_event* createEventList(JNIEnv *env, jobjectArray event_list, cl_uint num_even */ cl_device_id* createDeviceList(JNIEnv *env, jobjectArray device_list, cl_uint num_devices) { - cl_device_id *nativeDevice_list = new cl_device_id[num_devices]; + cl_device_id *nativeDevice_list = new (std::nothrow) cl_device_id[num_devices]; if (nativeDevice_list == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -544,6 +545,7 @@ cl_device_id* createDeviceList(JNIEnv *env, jobjectArray device_list, cl_uint nu cl_uint device_listLength = (cl_uint)env->GetArrayLength(device_list); if (device_listLength < num_devices) { + delete[] nativeDevice_list; ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", "Device list size is smaller than specified number of devices"); return NULL; @@ -582,7 +584,7 @@ cl_device_id* createDeviceList(JNIEnv *env, jobjectArray device_list, cl_uint nu */ cl_mem* createMemList(JNIEnv *env, jobjectArray mem_list, cl_uint num_mems) { - cl_mem *nativeMem_list = new cl_mem[num_mems]; + cl_mem *nativeMem_list = new (std::nothrow) cl_mem[num_mems]; if (nativeMem_list == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -593,6 +595,7 @@ cl_mem* createMemList(JNIEnv *env, jobjectArray mem_list, cl_uint num_mems) cl_uint mem_listLength = (cl_uint)env->GetArrayLength(mem_list); if (mem_listLength < num_mems) { + delete[] nativeMem_list; ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", "Memory object list size is smaller than specified number of memory objects"); return NULL; @@ -631,7 +634,7 @@ cl_mem* createMemList(JNIEnv *env, jobjectArray mem_list, cl_uint num_mems) */ void** createSvmPointers(JNIEnv *env, jobjectArray svm_pointers, cl_uint num_svm_pointers) { - void** nativeSvm_pointers = new void*[num_svm_pointers]; + void** nativeSvm_pointers = new (std::nothrow) void*[num_svm_pointers]; if (nativeSvm_pointers == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -642,6 +645,7 @@ void** createSvmPointers(JNIEnv *env, jobjectArray svm_pointers, cl_uint num_svm cl_uint svm_pointersLength = (cl_uint)env->GetArrayLength(svm_pointers); if (svm_pointersLength < num_svm_pointers) { + delete[] nativeSvm_pointers; ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", "Pointer array size is smaller than specified number of pointers"); return NULL; @@ -680,7 +684,7 @@ void** createSvmPointers(JNIEnv *env, jobjectArray svm_pointers, cl_uint num_svm */ cl_program* createProgramList(JNIEnv *env, jobjectArray program_list, cl_uint num_programs) { - cl_program* nativeProgram_list = new cl_program[num_programs]; + cl_program* nativeProgram_list = new (std::nothrow) cl_program[num_programs]; if (nativeProgram_list == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -691,6 +695,7 @@ cl_program* createProgramList(JNIEnv *env, jobjectArray program_list, cl_uint nu cl_uint program_listLength = (cl_uint)env->GetArrayLength(program_list); if (program_listLength < num_programs) { + delete[] nativeProgram_list; ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", "Program list size is smaller than specified number of programs"); return NULL; @@ -728,7 +733,7 @@ CallbackInfo* initCallbackInfo(JNIEnv *env, jobject pfn_notify, jobject user_dat { Logger::log(LOG_DEBUGTRACE, "Executing initCallbackInfo\n"); - CallbackInfo *callbackInfo = new CallbackInfo(); + CallbackInfo *callbackInfo = new (std::nothrow) CallbackInfo(); if (callbackInfo == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -795,8 +800,9 @@ void destroyCallbackInfo(JNIEnv *env, cl_context context) contextCallbackMap.find(context); if (iter != contextCallbackMap.end()) { + CallbackInfo* c = iter->second; contextCallbackMap.erase(iter); - deleteCallbackInfo(env, iter->second); + deleteCallbackInfo(env, c); } } diff --git a/src/main/native/ConversionsCL.cpp b/src/main/native/ConversionsCL.cpp index 0809893..2b34088 100644 --- a/src/main/native/ConversionsCL.cpp +++ b/src/main/native/ConversionsCL.cpp @@ -103,7 +103,7 @@ bool initNative_size_t(JNIEnv *env, jlongArray javaObject, size_t* &nativeObject return true; } jsize length = env->GetArrayLength(javaObject); - nativeObject = new size_t[size_t(length)]; + nativeObject = new (std::nothrow) size_t[size_t(length)]; if (nativeObject == nullptr) { ThrowByName(env, "java/lang/OutOfMemoryError", diff --git a/src/main/native/ConversionsCL.hpp b/src/main/native/ConversionsCL.hpp index 19d0862..c902bd7 100644 --- a/src/main/native/ConversionsCL.hpp +++ b/src/main/native/ConversionsCL.hpp @@ -31,6 +31,7 @@ #include #include +#include #include "JOCLCommon.hpp" #include "JNIUtils.hpp" @@ -61,7 +62,7 @@ bool initNativeGenericFixedSize( return true; } jsize length = env->GetArrayLength(javaObject); - nativeObject = new NativeType[size_t(length)]; + nativeObject = new (std::nothrow) NativeType[size_t(length)]; if (nativeObject == nullptr) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -189,7 +190,7 @@ bool initNativeGenericNativePointerObjectArray( } jsize length = env->GetArrayLength(objects); - objects_native = new NativeType[size_t(length)]; + objects_native = new (std::nothrow) NativeType[size_t(length)]; if (objects_native == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", diff --git a/src/main/native/JNIUtils.cpp b/src/main/native/JNIUtils.cpp index 48f3d38..2dd383e 100644 --- a/src/main/native/JNIUtils.cpp +++ b/src/main/native/JNIUtils.cpp @@ -26,6 +26,7 @@ */ #include +#include #include "JNIUtils.hpp" #include "Logger.hpp" @@ -258,7 +259,7 @@ char *convertString(JNIEnv *env, jstring js, int *length) { *length = (int)len; } - result = new char[(size_t)(len + 1)]; + result = new (std::nothrow) char[(size_t)(len + 1)]; if (result == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -283,7 +284,7 @@ char *convertString(JNIEnv *env, jstring js, int *length) size_t* convertArray(JNIEnv *env, jlongArray array) { jsize arrayLength = env->GetArrayLength(array); - size_t *result = new size_t[(size_t)arrayLength]; + size_t *result = new (std::nothrow) size_t[(size_t)arrayLength]; if (result == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -293,6 +294,7 @@ size_t* convertArray(JNIEnv *env, jlongArray array) jlong *jArray = (jlong*)env->GetPrimitiveArrayCritical(array, NULL); if (jArray == NULL) { + delete[] result; return NULL; } for (int i=0; iGetArrayLength(bytes); - nativeString = new char[(size_t)(len + 1)]; + nativeString = new (std::nothrow) char[(size_t)(len + 1)]; if (nativeString == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -353,7 +355,7 @@ bool initNative(JNIEnv *env, jobjectArray javaObject, char** &nativeObject, bool } jsize length = env->GetArrayLength(javaObject); delete[] nativeObject; - nativeObject = new char*[(size_t)length]; + nativeObject = new (std::nothrow) char*[(size_t)length]; for (jsize index = 0; index < length; index++) { jobject javaElement = env->GetObjectArrayElement(javaObject, index); diff --git a/src/main/native/PointerUtils.cpp b/src/main/native/PointerUtils.cpp index f5dabea..2017df4 100644 --- a/src/main/native/PointerUtils.cpp +++ b/src/main/native/PointerUtils.cpp @@ -28,6 +28,7 @@ #include "PointerUtils.hpp" #include "JNIUtils.hpp" #include "Logger.hpp" +#include // Class and method ID for org.jocl.Pointer and its constructor @@ -115,7 +116,7 @@ PointerData* initPointerData(JNIEnv *env, jobject pointerObject) { Logger::log(LOG_DEBUGTRACE, "Initializing pointer data for Java Pointer object %p\n", pointerObject); - PointerData *pointerData = new PointerData(); + PointerData *pointerData = new (std::nothrow) PointerData(); if (pointerData == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", @@ -166,11 +167,12 @@ PointerData* initPointerData(JNIEnv *env, jobject pointerObject) // Create an array containing the native representations of the // pointers, and store them as the data of the pointerData jsize size = env->GetArrayLength(pointersArray); - void **localPointer = new void*[(size_t)size]; + void **localPointer = new (std::nothrow) void*[(size_t)size]; PointerData **localPointerDatas = new PointerData*[(size_t)size]; if (localPointer == NULL) { + delete[] localPointerDatas; ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while obtaining native pointers"); return NULL; @@ -180,6 +182,8 @@ PointerData* initPointerData(JNIEnv *env, jobject pointerObject) jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { + delete[] localPointer; + delete[] localPointerDatas; return NULL; } if (p != NULL)