src/share/vm/prims/jvm.cpp

changeset 1100
c89f86385056
parent 1014
0fbdb4381b99
child 1111
d3676b4cb78c
     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");

mercurial