Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4323963

JVM_GetCP*UTF() functions are not thread safe

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 1.2.2_011
    • 1.2.0
    • hotspot
    • 011
    • generic
    • generic

        CLASS_UNLOCK(EE2SysThread(ee));
        + mb = cbMethods(cbCalled);
        + for (; --n >= 0; mb++) {
        + if ((mb->fb.name == cp[name_index].cp) &&
        + (mb->fb.signature == cp[signature_index].cp)) {
        + return mb->fb.access & ACC_WRITTEN_FLAGS;
        + }
                    }
        + return -1;
                }
        - return -1;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
             }
        + case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + return cp[cp_index].mb->fb.access & ACC_WRITTEN_FLAGS;
             default:
                 (*env)->FatalError(env, "JVM_GetCPMethodModifiers: illegal constant");
             }
             return 0; /* never reached */
         }
         
         JNIEXPORT void JNICALL
         JVM_ReleaseUTF(const char *utf)
         {
         }
         
         JNIEXPORT jboolean JNICALL
         JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2)
         {
             ClassClass *cb1 = (ClassClass *)DeRef(env, class1);
             ClassClass *cb2 = (ClassClass *)DeRef(env, class2);
             return IsSameClassPackage(cb1, cb2);
         }
         
         /*
          * Thread class calls
          */
        (Review ID: 102695)
        ======================================================================


        Name: clC74495 Date: 03/22/2000


        In
            src/share/javavm/runtime/jvm.c
        the accesses of unresolved constant pool entries are not thread safe.

        JVM_GetCPFieldNameUTF() is a good example. This thread interaction is
        possible:

            switch(type_table[cp_index]) {
            case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
                return cp[cp_index].fb->name;
            case CONSTANT_Fieldref: {
        >>> ANOTHER THREAD RESOLVES CONSTANT POOL ENTRY!
                int index = cp[cp_index].i; /* value of Fieldref field */

        The constant pool entry will have changed before JVM_GetCPFieldNameUTF()
        has read it!

        A locking mechanism similar to that used in ResolveClassConstant0()
        or GetClassConstantClassName() should be used here too. In that code
        all accesses to unresolved constant pool entries are guarded using the
        LINKCLASS lock.

        The other JVM_GetCP*UTF() functions have the same problem. The diffs
        below show the way I fixed this. The changes for each function are
        very similar. The changes should be similar for JDK 1.3.


        --------
        --- current/jvm.c Tue Dec 1 13:43:12 1998
        +++ fix/jvm.c Mon Mar 20 17:58:42 2000
        @@ -1721,237 +1721,301 @@
         JVM_GetMethodIxNameUTF(JNIEnv *env, jclass c, jint index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             struct methodblock *mb = cbMethods(cb) + index;
             return mb->fb.name;
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass c, jint index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             struct methodblock *mb = cbMethods(cb) + index;
             return mb->fb.signature;
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetCPFieldNameUTF(JNIEnv *env, jclass c, jint cp_index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        + case CONSTANT_Fieldref: {
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned index = cp[cp_index].i; /* value of Fieldref field */
        + unsigned key2 = index & 0xFFFF; /* index to NameAndType */
        + unsigned name_index = cp[key2].i >> 16;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + return cp[name_index].cp;
        + }
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
        + }
             case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
                 return cp[cp_index].fb->name;
        - case CONSTANT_Fieldref: {
        - int index = cp[cp_index].i; /* value of Fieldref field */
        - int key2 = index & 0xFFFF; /* index to NameAndType */
        - int name_index = cp[key2].i >> 16;
        - return cp[name_index].cp;
        - }
             default:
                 (*env)->FatalError(env, "JVM_GetCPFieldNameUTF: illegal constant");
                return NULL; /* Keep lint happy */
             }
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetCPMethodNameUTF(JNIEnv *env, jclass c, jint cp_index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        - case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - return cp[cp_index].mb->fb.name;
             case CONSTANT_InterfaceMethodref:
             case CONSTANT_Methodref: {
        - int index = cp[cp_index].i;
        - int key2 = index & 0xFFFF; /* index to NameAndType */
        - int name_index = cp[key2].i >> 16;
        - return cp[name_index].cp;
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned index = cp[cp_index].i; /* value of Fieldref field */
        + unsigned key2 = index & 0xFFFF; /* index to NameAndType */
        + unsigned name_index = cp[key2].i >> 16;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + return cp[name_index].cp;
        + }
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
             }
        + case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + return cp[cp_index].mb->fb.name;
             default:
                 (*env)->FatalError(env, "JVM_GetCPMethodNameUTF: illegal constant");
                return NULL; /* Keep lint happy */
             }
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass c, jint cp_index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        + case CONSTANT_Fieldref: {
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned index = cp[cp_index].i; /* value of Fieldref field */
        + unsigned key2 = index & 0xFFFF; /* index to NameAndType */
        + unsigned signature_index = cp[key2].i & 0xFFFF;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + return cp[signature_index].cp;
        + }
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
        + }
             case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
                 return cp[cp_index].fb->signature;
        - case CONSTANT_Fieldref: {
        - int index = cp[cp_index].i; /* value of Fieldref field */
        - int key2 = index & 0xFFFF; /* index to NameAndType */
        - int signature_index = cp[key2].i & 0xFFFF;
        - return cp[signature_index].cp;
        - }
             default:
                 (*env)->FatalError(env, "JVM_GetCPFieldSignatureUTF: illegal constant");
                return NULL; /* Keep lint happy */
             }
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass c, jint cp_index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        - case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - return cp[cp_index].mb->fb.signature;
             case CONSTANT_InterfaceMethodref:
             case CONSTANT_Methodref: {
        - int index = cp[cp_index].i;
        - int key2 = index & 0xFFFF; /* index to NameAndType */
        - int signature_index = cp[key2].i & 0xFFFF;
        - return cp[signature_index].cp;
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned index = cp[cp_index].i; /* value of Fieldref field */
        + unsigned key2 = index & 0xFFFF; /* index to NameAndType */
        + unsigned signature_index = cp[key2].i & 0xFFFF;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + return cp[signature_index].cp;
        + }
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
             }
        + case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + return cp[cp_index].mb->fb.signature;
             default:
                 (*env)->FatalError(env, "JVM_GetCPMethodSignatureUTF: illegal constant");
                return NULL; /* Keep lint happy */
             }
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetCPClassNameUTF(JNIEnv *env, jclass c, jint cp_index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             union cp_item_type *cp = cbConstantPool(cb);
             return GetClassConstantClassName(cp, cp_index);
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass c, jint cp_index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        + case CONSTANT_Fieldref: {
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned classkey = cp[cp_index].i >> 16;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + return GetClassConstantClassName(cp, classkey);
        + }
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
        + }
             case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
                 return cbName(cp[cp_index].fb->clazz);
        - case CONSTANT_Fieldref: {
        - unsigned classkey = cp[cp_index].i >> 16;
        - return GetClassConstantClassName(cp, classkey);
        - }
             default:
                 (*env)->FatalError(env, "JVM_GetCPFieldClassNameUTF: illegal constant");
                return NULL; /* Keep lint happy */
             }
         }
         
         JNIEXPORT const char * JNICALL
         JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass c, jint cp_index)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        - case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - return cbName(cp[cp_index].mb->fb.clazz);
             case CONSTANT_InterfaceMethodref:
             case CONSTANT_Methodref: {
        - unsigned classkey = cp[cp_index].i >> 16;
        - return GetClassConstantClassName(cp, classkey);
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned classkey = cp[cp_index].i >> 16;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + return GetClassConstantClassName(cp, classkey);
        + }
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
             }
        + case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        + return cbName(cp[cp_index].mb->fb.clazz);
             default:
                 (*env)->FatalError(env, "JVM_GetCPMethodClassNameUTF: illegal constant");
                return NULL; /* Keep lint happy */
             }
         }
         
         JNIEXPORT jint JNICALL
         JVM_GetCPFieldModifiers(JNIEnv *env, jclass c, int cp_index,
                                jclass calledClass)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             ClassClass *cbCalled = (ClassClass *)DeRef(env, calledClass);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        - case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
        - return cp[cp_index].fb->access & ACC_WRITTEN_FLAGS;
        - case CONSTANT_Fieldref: {
        - int index = cp[cp_index].i; /* value of Fieldref field */
        - int key2 = index & 0xFFFF; /* index to NameAndType */
        - int signature_index = cp[key2].i & 0xFFFF;
        - int name_index = cp[key2].i >> 16;
        - struct fieldblock *fb;
        - int n = cbFieldsCount(cbCalled);
        -
        - fb = cbFields(cbCalled);
        - for (; --n >= 0; fb++) {
        - if ((fb->name == cp[name_index].cp) &&
        - (fb->signature == cp[signature_index].cp)) {
        - return fb->access & ACC_WRITTEN_FLAGS;
        + case CONSTANT_Fieldref: {
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned index = cp[cp_index].i; /* value of Fieldref field */
        + unsigned key2 = index & 0xFFFF; /* index to NameAndType */
        + unsigned signature_index = cp[key2].i & 0xFFFF;
        + unsigned name_index = cp[key2].i >> 16;
        + struct fieldblock *fb;
        + int n = cbFieldsCount(cbCalled);
        +
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + fb = cbFields(cbCalled);
        + for (; --n >= 0; fb++) {
        + if ((fb->name == cp[name_index].cp) &&
        + (fb->signature == cp[signature_index].cp)) {
        + return fb->access & ACC_WRITTEN_FLAGS;
        + }
                    }
        + return -1;
                }
        - return -1;
        + LINKCLASS_UNLOCK(EE2SysThread(ee));
        + /* FALL THROUGH */
             }
        + case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
        + return cp[cp_index].fb->access & ACC_WRITTEN_FLAGS;
             default:
                 (*env)->FatalError(env, "JVM_GetCPFieldModifiers: illegal constant");
             }
             return 0; /* never reached */
         }
             
         JNIEXPORT jint JNICALL
         JVM_GetCPMethodModifiers(JNIEnv *env, jclass c, int cp_index,
                                 jclass calledClass)
         {
             ClassClass *cb = (ClassClass *)DeRef(env, c);
             ClassClass *cbCalled = (ClassClass *)DeRef(env, calledClass);
             union cp_item_type *cp = cbConstantPool(cb);
             unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
             switch(type_table[cp_index]) {
        - case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
        - return cp[cp_index].mb->fb.access & ACC_WRITTEN_FLAGS;
             case CONSTANT_InterfaceMethodref:
             case CONSTANT_Methodref: {
        - int index = cp[cp_index].i; /* value of Fieldref field */
        - int key2 = index & 0xFFFF; /* index to NameAndType */
        - int signature_index = cp[key2].i & 0xFFFF;
        - int name_index = cp[key2].i >> 16;
        - struct methodblock *mb;
        - int n = cbMethodsCount(cbCalled);
        - mb = cbMethods(cbCalled);
        -
        - for (; --n >= 0; mb++) {
        - if ((mb->fb.name == cp[name_index].cp) &&
        - (mb->fb.signature == cp[signature_index].cp)) {
        - return mb->fb.access & ACC_WRITTEN_FLAGS;
        + ExecEnv *ee = JNIEnv2EE(env);
        + LINKCLASS_LOCK(EE2SysThread(ee));
        + /* Entry may have been resolved by another thread */
        + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, cp_index)) {
        + unsigned index = cp[cp_index].i; /* value of Fieldref field */
        + unsigned key2 = index & 0xFFFF; /* index to NameAndType */
        + unsigned signature_index = cp[key2].i & 0xFFFF;
        + unsigned name_index = cp[key2].i >> 16;
        + struct methodblock *mb;
        + int n = cbMethodsCount(cbCalled);
        +
        + LINK

              coleenp Coleen Phillimore
              clucasius Carlos Lucasius (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: