8025922: JNI access to Strings need to check if the value field is non-null
Reviewed-by: dholmes, dcubed
--- a/hotspot/src/share/vm/prims/jni.cpp Fri Oct 04 13:01:07 2013 +0200
+++ b/hotspot/src/share/vm/prims/jni.cpp Sat Oct 05 15:18:57 2013 +0200
@@ -3210,7 +3210,11 @@
HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(
env, string);
#endif /* USDT2 */
- jsize ret = java_lang_String::length(JNIHandles::resolve_non_null(string));
+ jsize ret = 0;
+ oop s = JNIHandles::resolve_non_null(string);
+ if (java_lang_String::value(s) != NULL) {
+ ret = java_lang_String::length(s);
+ }
#ifndef USDT2
DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret);
#else /* USDT2 */
@@ -3230,20 +3234,23 @@
HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(
env, string, (uintptr_t *) isCopy);
#endif /* USDT2 */
+ jchar* buf = NULL;
oop s = JNIHandles::resolve_non_null(string);
- int s_len = java_lang_String::length(s);
typeArrayOop s_value = java_lang_String::value(s);
- int s_offset = java_lang_String::offset(s);
- jchar* buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
- /* JNI Specification states return NULL on OOM */
- if (buf != NULL) {
- if (s_len > 0) {
- memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);
- }
- buf[s_len] = 0;
- //%note jni_5
- if (isCopy != NULL) {
- *isCopy = JNI_TRUE;
+ if (s_value != NULL) {
+ int s_len = java_lang_String::length(s);
+ int s_offset = java_lang_String::offset(s);
+ buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
+ /* JNI Specification states return NULL on OOM */
+ if (buf != NULL) {
+ if (s_len > 0) {
+ memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);
+ }
+ buf[s_len] = 0;
+ //%note jni_5
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
}
}
#ifndef USDT2
@@ -3313,7 +3320,11 @@
HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(
env, string);
#endif /* USDT2 */
- jsize ret = java_lang_String::utf8_length(JNIHandles::resolve_non_null(string));
+ jsize ret = 0;
+ oop java_string = JNIHandles::resolve_non_null(string);
+ if (java_lang_String::value(java_string) != NULL) {
+ ret = java_lang_String::utf8_length(java_string);
+ }
#ifndef USDT2
DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret);
#else /* USDT2 */
@@ -3332,14 +3343,17 @@
HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(
env, string, (uintptr_t *) isCopy);
#endif /* USDT2 */
+ char* result = NULL;
oop java_string = JNIHandles::resolve_non_null(string);
- size_t length = java_lang_String::utf8_length(java_string);
- /* JNI Specification states return NULL on OOM */
- char* result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
- if (result != NULL) {
- java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
- if (isCopy != NULL) {
- *isCopy = JNI_TRUE;
+ if (java_lang_String::value(java_string) != NULL) {
+ size_t length = java_lang_String::utf8_length(java_string);
+ /* JNI Specification states return NULL on OOM */
+ result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
+ if (result != NULL) {
+ java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
+ if (isCopy != NULL) {
+ *isCopy = JNI_TRUE;
+ }
}
}
#ifndef USDT2
--- a/hotspot/src/share/vm/prims/jniCheck.cpp Fri Oct 04 13:01:07 2013 +0200
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp Sat Oct 05 15:18:57 2013 +0200
@@ -1324,18 +1324,19 @@
IN_VM(
checkString(thr, str);
)
+ jchar* newResult = NULL;
const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
-
- size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
- jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
- *tagLocation = STRING_TAG;
- jchar* newResult = (jchar*) (tagLocation + 1);
- memcpy(newResult, result, len * sizeof(jchar));
- // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
- // Note that the dtrace arguments for the allocated memory will not match up with this solution.
- FreeHeap((char*)result);
-
+ if (result != NULL) {
+ size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
+ jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
+ *tagLocation = STRING_TAG;
+ newResult = (jchar*) (tagLocation + 1);
+ memcpy(newResult, result, len * sizeof(jchar));
+ // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
+ // Note that the dtrace arguments for the allocated memory will not match up with this solution.
+ FreeHeap((char*)result);
+ }
functionExit(env);
return newResult;
JNI_END
@@ -1394,18 +1395,19 @@
IN_VM(
checkString(thr, str);
)
+ char* newResult = NULL;
const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
-
- size_t len = strlen(result) + 1; // + 1 for NULL termination
- jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
- *tagLocation = STRING_UTF_TAG;
- char* newResult = (char*) (tagLocation + 1);
- strcpy(newResult, result);
- // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
- // Note that the dtrace arguments for the allocated memory will not match up with this solution.
- FreeHeap((char*)result, mtInternal);
-
+ if (result != NULL) {
+ size_t len = strlen(result) + 1; // + 1 for NULL termination
+ jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
+ *tagLocation = STRING_UTF_TAG;
+ newResult = (char*) (tagLocation + 1);
+ strcpy(newResult, result);
+ // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
+ // Note that the dtrace arguments for the allocated memory will not match up with this solution.
+ FreeHeap((char*)result, mtInternal);
+ }
functionExit(env);
return newResult;
JNI_END