src/share/vm/prims/jniCheck.cpp

Print this page
rev 1876 : 6539281 -Xcheck:jni should validate char* argument to ReleaseStringUTFChars

@@ -1286,36 +1286,48 @@
     jsize result = UNCHECKED()->GetStringLength(env,str);
     functionExit(env);
     return result;
 JNI_END
 
+// Arbitrary (but well-known) tag
+#define STRING_TAG 0x47114711
+
 JNI_ENTRY_CHECKED(const jchar *,
   checked_jni_GetStringChars(JNIEnv *env,
                              jstring str,
                              jboolean *isCopy))
     functionEnter(thr);
     IN_VM(
       checkString(thr, str);
     )
     const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
+
+    size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
+    jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), "checked_jni_GetStringChars"); 
+    *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
+    FreeHeap((char*)result);
+
     functionExit(env);
-    return result;
+    return newResult;
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
   checked_jni_ReleaseStringChars(JNIEnv *env,
                                  jstring str,
                                  const jchar *chars))
     functionEnterExceptionAllowed(thr);
     IN_VM(
       checkString(thr, str);
     )
-    /* cannot check validity of copy, unless every request is logged by
-     * checking code.  Implementation of this check is deferred until a
-     * subsequent release.
-     */
-    UNCHECKED()->ReleaseStringChars(env,str,chars);
+    jint *tagLocation = ((jint*) chars) - 1;
+    if (*tagLocation != STRING_TAG) {
+       NativeReportJNIFatalError(thr, "ReleaseStringChars called on something not allocated by GetStringChars");
+    }
+    UNCHECKED()->ReleaseStringChars(env,str,(const jchar*)tagLocation);
     functionExit(env);
 JNI_END
 
 JNI_ENTRY_CHECKED(jstring,
   checked_jni_NewStringUTF(JNIEnv *env,

@@ -1336,36 +1348,48 @@
     jsize result = UNCHECKED()->GetStringUTFLength(env,str);
     functionExit(env);
     return result;
 JNI_END
 
+// Arbitrary (but well-known) tag - different than GetStringChars
+#define STRING_UTF_TAG 0x48124812
+
 JNI_ENTRY_CHECKED(const char *,
   checked_jni_GetStringUTFChars(JNIEnv *env,
                                 jstring str,
                                 jboolean *isCopy))
     functionEnter(thr);
     IN_VM(
       checkString(thr, str);
     )
     const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
+
+    size_t len = strlen(result) + 1; // + 1 for NULL termination
+    jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), "checked_jni_GetStringUTFChars");
+    *tagLocation = STRING_UTF_TAG;
+    char* newResult = (char*) (tagLocation + 1);
+    strcpy(newResult, result);
+    // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
+    FreeHeap((char*)result);
+
     functionExit(env);
-    return result;
+    return newResult;
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
   checked_jni_ReleaseStringUTFChars(JNIEnv *env,
                                     jstring str,
                                     const char* chars))
     functionEnterExceptionAllowed(thr);
     IN_VM(
       checkString(thr, str);
     )
-    /* cannot check validity of copy, unless every request is logged by
-     * checking code.  Implementation of this check is deferred until a
-     * subsequent release.
-     */
-    UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
+    jint* tagLocation = ((jint*) chars) - 1;
+    if (*tagLocation != STRING_UTF_TAG) {
+       NativeReportJNIFatalError(thr, "ReleaseStringUTFChars called on something not allocated by GetStringUTFChars");
+    }
+    UNCHECKED()->ReleaseStringUTFChars(env,str,(const char*)tagLocation);
     functionExit(env);
 JNI_END
 
 JNI_ENTRY_CHECKED(jsize,
   checked_jni_GetArrayLength(JNIEnv *env,