1.1 --- a/src/share/vm/prims/jvm.cpp Thu Mar 19 09:13:24 2009 -0700 1.2 +++ b/src/share/vm/prims/jvm.cpp Fri Mar 20 23:19:36 2009 -0700 1.3 @@ -1242,7 +1242,7 @@ 1.4 1.5 // Throws an exception if outer klass has not declared k as 1.6 // an inner klass 1.7 - Reflection::check_for_inner_class(k, inner_klass, CHECK_NULL); 1.8 + Reflection::check_for_inner_class(k, inner_klass, true, CHECK_NULL); 1.9 1.10 result->obj_at_put(members, inner_klass->java_mirror()); 1.11 members++; 1.12 @@ -1265,16 +1265,29 @@ 1.13 1.14 1.15 JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)) 1.16 - const int inner_class_info_index = 0; 1.17 - const int outer_class_info_index = 1; 1.18 - 1.19 +{ 1.20 // ofClass is a reference to a java_lang_Class object. 1.21 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || 1.22 ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { 1.23 return NULL; 1.24 } 1.25 1.26 - instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); 1.27 + symbolOop simple_name = NULL; 1.28 + klassOop outer_klass 1.29 + = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)) 1.30 + )->compute_enclosing_class(simple_name, CHECK_NULL); 1.31 + if (outer_klass == NULL) return NULL; // already a top-level class 1.32 + if (simple_name == NULL) return NULL; // an anonymous class (inside a method) 1.33 + return (jclass) JNIHandles::make_local(env, Klass::cast(outer_klass)->java_mirror()); 1.34 +} 1.35 +JVM_END 1.36 + 1.37 +// should be in instanceKlass.cpp, but is here for historical reasons 1.38 +klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k, 1.39 + symbolOop& simple_name_result, TRAPS) { 1.40 + Thread* thread = THREAD; 1.41 + const int inner_class_info_index = inner_class_inner_class_info_offset; 1.42 + const int outer_class_info_index = inner_class_outer_class_info_offset; 1.43 1.44 if (k->inner_classes()->length() == 0) { 1.45 // No inner class info => no declaring class 1.46 @@ -1288,35 +1301,51 @@ 1.47 bool found = false; 1.48 klassOop ok; 1.49 instanceKlassHandle outer_klass; 1.50 + bool inner_is_member = false; 1.51 + int simple_name_index = 0; 1.52 1.53 // Find inner_klass attribute 1.54 - for(int i = 0; i < i_length && !found; i+= 4) { 1.55 + for (int i = 0; i < i_length && !found; i += inner_class_next_offset) { 1.56 int ioff = i_icls->ushort_at(i + inner_class_info_index); 1.57 int ooff = i_icls->ushort_at(i + outer_class_info_index); 1.58 - 1.59 - if (ioff != 0 && ooff != 0) { 1.60 + int noff = i_icls->ushort_at(i + inner_class_inner_name_offset); 1.61 + if (ioff != 0) { 1.62 // Check to see if the name matches the class we're looking for 1.63 // before attempting to find the class. 1.64 if (i_cp->klass_name_at_matches(k, ioff)) { 1.65 klassOop inner_klass = i_cp->klass_at(ioff, CHECK_NULL); 1.66 - if (k() == inner_klass) { 1.67 - found = true; 1.68 + found = (k() == inner_klass); 1.69 + if (found && ooff != 0) { 1.70 ok = i_cp->klass_at(ooff, CHECK_NULL); 1.71 outer_klass = instanceKlassHandle(thread, ok); 1.72 + simple_name_index = noff; 1.73 + inner_is_member = true; 1.74 } 1.75 } 1.76 } 1.77 } 1.78 1.79 + if (found && outer_klass.is_null()) { 1.80 + // It may be anonymous; try for that. 1.81 + int encl_method_class_idx = k->enclosing_method_class_index(); 1.82 + if (encl_method_class_idx != 0) { 1.83 + ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL); 1.84 + outer_klass = instanceKlassHandle(thread, ok); 1.85 + inner_is_member = false; 1.86 + } 1.87 + } 1.88 + 1.89 // If no inner class attribute found for this class. 1.90 - if (!found) return NULL; 1.91 + if (outer_klass.is_null()) return NULL; 1.92 1.93 // Throws an exception if outer klass has not declared k as an inner klass 1.94 - Reflection::check_for_inner_class(outer_klass, k, CHECK_NULL); 1.95 - 1.96 - return (jclass)JNIHandles::make_local(env, outer_klass->java_mirror()); 1.97 -JVM_END 1.98 - 1.99 + // We need evidence that each klass knows about the other, or else 1.100 + // the system could allow a spoof of an inner class to gain access rights. 1.101 + Reflection::check_for_inner_class(outer_klass, k, inner_is_member, CHECK_NULL); 1.102 + 1.103 + simple_name_result = (inner_is_member ? i_cp->symbol_at(simple_name_index) : symbolOop(NULL)); 1.104 + return outer_klass(); 1.105 +} 1.106 1.107 JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls)) 1.108 assert (cls != NULL, "illegal class");