Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit 6ddce64

Browse files
hseigelHarold Seigel
authored andcommitted
8243302: Advanced class supports
Reviewed-by: coleenp, lfoltan, mschoene, rhalade
1 parent 58a515e commit 6ddce64

File tree

2 files changed

+94
-11
lines changed

2 files changed

+94
-11
lines changed

src/hotspot/share/classfile/classFileParser.cpp

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,8 +3087,83 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(const Cla
30873087
JVM_ACC_STATIC \
30883088
)
30893089

3090+
// Find index of the InnerClasses entry for the specified inner_class_info_index.
3091+
// Return -1 if none is found.
3092+
static int inner_classes_find_index(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) {
3093+
Symbol* cp_klass_name = cp->klass_name_at(inner);
3094+
for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) {
3095+
int idx_inner = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset);
3096+
if (cp->klass_name_at(idx_inner) == cp_klass_name) {
3097+
return idx;
3098+
}
3099+
}
3100+
return -1;
3101+
}
3102+
3103+
// Return the outer_class_info_index for the InnerClasses entry containing the
3104+
// specified inner_class_info_index. Return -1 if no InnerClasses entry is found.
3105+
static int inner_classes_jump_to_outer(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) {
3106+
if (inner == 0) return -1;
3107+
int idx = inner_classes_find_index(inner_classes, inner, cp, length);
3108+
if (idx == -1) return -1;
3109+
int result = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset);
3110+
return result;
3111+
}
3112+
3113+
// Return true if circularity is found, false if no circularity is found.
3114+
// Use Floyd's cycle finding algorithm.
3115+
static bool inner_classes_check_loop_through_outer(const Array<u2>* inner_classes, int idx, const ConstantPool* cp, int length) {
3116+
int slow = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset);
3117+
int fast = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset);
3118+
while (fast != -1 && fast != 0) {
3119+
if (slow != 0 && (cp->klass_name_at(slow) == cp->klass_name_at(fast))) {
3120+
return true; // found a circularity
3121+
}
3122+
fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length);
3123+
if (fast == -1) return false;
3124+
fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length);
3125+
if (fast == -1) return false;
3126+
slow = inner_classes_jump_to_outer(inner_classes, slow, cp, length);
3127+
assert(slow != -1, "sanity check");
3128+
}
3129+
return false;
3130+
}
3131+
3132+
// Loop through each InnerClasses entry checking for circularities and duplications
3133+
// with other entries. If duplicate entries are found then throw CFE. Otherwise,
3134+
// return true if a circularity or entries with duplicate inner_class_info_indexes
3135+
// are found.
3136+
bool ClassFileParser::check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPS) {
3137+
// Loop through each InnerClasses entry.
3138+
for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) {
3139+
// Return true if there are circular entries.
3140+
if (inner_classes_check_loop_through_outer(_inner_classes, idx, cp, length)) {
3141+
return true;
3142+
}
3143+
// Check if there are duplicate entries or entries with the same inner_class_info_index.
3144+
for (int y = idx + InstanceKlass::inner_class_next_offset; y < length;
3145+
y += InstanceKlass::inner_class_next_offset) {
3146+
3147+
// To maintain compatibility, throw an exception if duplicate inner classes
3148+
// entries are found.
3149+
guarantee_property((_inner_classes->at(idx) != _inner_classes->at(y) ||
3150+
_inner_classes->at(idx+1) != _inner_classes->at(y+1) ||
3151+
_inner_classes->at(idx+2) != _inner_classes->at(y+2) ||
3152+
_inner_classes->at(idx+3) != _inner_classes->at(y+3)),
3153+
"Duplicate entry in InnerClasses attribute in class file %s",
3154+
CHECK_(true));
3155+
// Return true if there are two entries with the same inner_class_info_index.
3156+
if (_inner_classes->at(y) == _inner_classes->at(idx)) {
3157+
return true;
3158+
}
3159+
}
3160+
}
3161+
return false;
3162+
}
3163+
30903164
// Return number of classes in the inner classes attribute table
30913165
u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs,
3166+
const ConstantPool* cp,
30923167
const u1* const inner_classes_attribute_start,
30933168
bool parsed_enclosingmethod_attribute,
30943169
u2 enclosing_method_class_index,
@@ -3112,7 +3187,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea
31123187
// enclosing_method_class_index,
31133188
// enclosing_method_method_index]
31143189
const int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
3115-
Array<u2>* const inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
3190+
Array<u2>* inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
31163191
_inner_classes = inner_classes;
31173192

31183193
int index = 0;
@@ -3163,25 +3238,28 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea
31633238
}
31643239

31653240
// 4347400: make sure there's no duplicate entry in the classes array
3241+
// Also, check for circular entries.
3242+
bool has_circularity = false;
31663243
if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
3167-
for(int i = 0; i < length * 4; i += 4) {
3168-
for(int j = i + 4; j < length * 4; j += 4) {
3169-
guarantee_property((inner_classes->at(i) != inner_classes->at(j) ||
3170-
inner_classes->at(i+1) != inner_classes->at(j+1) ||
3171-
inner_classes->at(i+2) != inner_classes->at(j+2) ||
3172-
inner_classes->at(i+3) != inner_classes->at(j+3)),
3173-
"Duplicate entry in InnerClasses in class file %s",
3174-
CHECK_0);
3244+
has_circularity = check_inner_classes_circularity(cp, length * 4, CHECK_0);
3245+
if (has_circularity) {
3246+
// If circularity check failed then ignore InnerClasses attribute.
3247+
MetadataFactory::free_array<u2>(_loader_data, _inner_classes);
3248+
index = 0;
3249+
if (parsed_enclosingmethod_attribute) {
3250+
inner_classes = MetadataFactory::new_array<u2>(_loader_data, 2, CHECK_0);
3251+
_inner_classes = inner_classes;
3252+
} else {
3253+
_inner_classes = Universe::the_empty_short_array();
31753254
}
31763255
}
31773256
}
3178-
31793257
// Set EnclosingMethod class and method indexes.
31803258
if (parsed_enclosingmethod_attribute) {
31813259
inner_classes->at_put(index++, enclosing_method_class_index);
31823260
inner_classes->at_put(index++, enclosing_method_method_index);
31833261
}
3184-
assert(index == size, "wrong size");
3262+
assert(index == size || has_circularity, "wrong size");
31853263

31863264
// Restore buffer's current position.
31873265
cfs->set_current(current_mark);
@@ -3564,6 +3642,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
35643642
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
35653643
const u2 num_of_classes = parse_classfile_inner_classes_attribute(
35663644
cfs,
3645+
cp,
35673646
inner_classes_attribute_start,
35683647
parsed_innerclasses_attribute,
35693648
enclosing_method_class_index,

src/hotspot/share/classfile/classFileParser.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,11 @@ class ClassFileParser {
276276
int length,
277277
TRAPS);
278278

279+
// Check for circularity in InnerClasses attribute.
280+
bool check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPS);
281+
279282
u2 parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs,
283+
const ConstantPool* cp,
280284
const u1* const inner_classes_attribute_start,
281285
bool parsed_enclosingmethod_attribute,
282286
u2 enclosing_method_class_index,

0 commit comments

Comments
 (0)