Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/lworld' into invalid_classes
Browse files Browse the repository at this point in the history
  • Loading branch information
fparain committed Jun 11, 2024
2 parents cedbae9 + 0a87e69 commit 624c50b
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 100 deletions.
6 changes: 3 additions & 3 deletions src/hotspot/share/cds/metaspaceShared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ bool MetaspaceShared::_use_optimized_module_handling = true;
// These regions are aligned with MetaspaceShared::core_region_alignment().
//
// These 2 regions are populated in the following steps:
// [0] All classes are loaded in MetaspaceShared::preload_classes(). All metadata are
// [0] All classes are loaded in MetaspaceShared::loadable_descriptors(). All metadata are
// temporarily allocated outside of the shared regions.
// [1] We enter a safepoint and allocate a buffer for the rw/ro regions.
// [2] C++ vtables are copied into the rw region.
Expand Down Expand Up @@ -727,7 +727,7 @@ void MetaspaceShared::get_default_classlist(char* default_classlist, const size_
}
}

void MetaspaceShared::preload_classes(TRAPS) {
void MetaspaceShared::loadable_descriptors(TRAPS) {
char default_classlist[JVM_MAXPATHLEN];
const char* classlist_path;

Expand Down Expand Up @@ -764,7 +764,7 @@ void MetaspaceShared::preload_classes(TRAPS) {
}

void MetaspaceShared::preload_and_dump_impl(TRAPS) {
preload_classes(CHECK);
loadable_descriptors(CHECK);

if (SharedArchiveConfigFile) {
log_info(cds)("Reading extra data from %s ...", SharedArchiveConfigFile);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/cds/metaspaceShared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class MetaspaceShared : AllStatic {

private:
static void preload_and_dump_impl(TRAPS) NOT_CDS_RETURN;
static void preload_classes(TRAPS) NOT_CDS_RETURN;
static void loadable_descriptors(TRAPS) NOT_CDS_RETURN;

public:
static Symbol* symbol_rs_base() {
Expand Down
102 changes: 61 additions & 41 deletions src/hotspot/share/classfile/classFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3364,29 +3364,39 @@ u2 ClassFileParser::parse_classfile_permitted_subclasses_attribute(const ClassFi
return length;
}

u2 ClassFileParser::parse_classfile_preload_attribute(const ClassFileStream* const cfs,
const u1* const preload_attribute_start,
u2 ClassFileParser::parse_classfile_loadable_descriptors_attribute(const ClassFileStream* const cfs,
const u1* const loadable_descriptors_attribute_start,
TRAPS) {
const u1* const current_mark = cfs->current();
u2 length = 0;
if (preload_attribute_start != nullptr) {
cfs->set_current(preload_attribute_start);
if (loadable_descriptors_attribute_start != nullptr) {
cfs->set_current(loadable_descriptors_attribute_start);
cfs->guarantee_more(2, CHECK_0); // length
length = cfs->get_u2_fast();
}
const int size = length;
Array<u2>* const preload_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
_preload_classes = preload_classes;
Array<u2>* const loadable_descriptors = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
_loadable_descriptors = loadable_descriptors;
if (length > 0) {
int index = 0;
cfs->guarantee_more(2 * length, CHECK_0);
for (int n = 0; n < length; n++) {
const u2 class_info_index = cfs->get_u2_fast();
const u2 descriptor_index = cfs->get_u2_fast();
check_property(
valid_klass_reference_at(class_info_index),
"Preload class_info_index %u has bad constant type in class file %s",
class_info_index, CHECK_0);
preload_classes->at_put(index++, class_info_index);
valid_symbol_at(descriptor_index),
"LoadableDescriptors descriptor_index %u has bad constant type in class file %s",
descriptor_index, CHECK_0);
Symbol* descriptor = _cp->symbol_at(descriptor_index);
bool valid = legal_field_signature(descriptor, CHECK_0);
if(!valid) {
ResourceMark rm(THREAD);
Exceptions::fthrow(THREAD_AND_LOCATION,
vmSymbols::java_lang_ClassFormatError(),
"Descriptor from LoadableDescriptors attribute at index \"%d\" in class %s has illegal signature \"%s\"",
descriptor_index, _class_name->as_C_string(), descriptor->as_C_string());
return 0;
}
loadable_descriptors->at_put(index++, descriptor_index);
}
assert(index == size, "wrong size");
}
Expand Down Expand Up @@ -3681,15 +3691,15 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
_nest_members = Universe::the_empty_short_array();
// Set _permitted_subclasses attribute to default sentinel
_permitted_subclasses = Universe::the_empty_short_array();
// Set _preload_classes attribute to default sentinel
_preload_classes = Universe::the_empty_short_array();
// Set _loadable_descriptors attribute to default sentinel
_loadable_descriptors = Universe::the_empty_short_array();
cfs->guarantee_more(2, CHECK); // attributes_count
u2 attributes_count = cfs->get_u2_fast();
bool parsed_sourcefile_attribute = false;
bool parsed_innerclasses_attribute = false;
bool parsed_nest_members_attribute = false;
bool parsed_permitted_subclasses_attribute = false;
bool parsed_preload_attribute = false;
bool parsed_loadable_descriptors_attribute = false;
bool parsed_nest_host_attribute = false;
bool parsed_record_attribute = false;
bool parsed_enclosingmethod_attribute = false;
Expand All @@ -3715,8 +3725,8 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
u4 record_attribute_length = 0;
const u1* permitted_subclasses_attribute_start = nullptr;
u4 permitted_subclasses_attribute_length = 0;
const u1* preload_attribute_start = nullptr;
u4 preload_attribute_length = 0;
const u1* loadable_descriptors_attribute_start = nullptr;
u4 loadable_descriptors_attribute_length = 0;

// Iterate over attributes
while (attributes_count--) {
Expand Down Expand Up @@ -3943,14 +3953,14 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
permitted_subclasses_attribute_start = cfs->current();
permitted_subclasses_attribute_length = attribute_length;
}
if (EnableValhalla && tag == vmSymbols::tag_preload()) {
if (parsed_preload_attribute) {
if (EnableValhalla && tag == vmSymbols::tag_loadable_descriptors()) {
if (parsed_loadable_descriptors_attribute) {
classfile_parse_error("Multiple Preload attributes in class file %s", CHECK);
return;
}
parsed_preload_attribute = true;
preload_attribute_start = cfs->current();
preload_attribute_length = attribute_length;
parsed_loadable_descriptors_attribute = true;
loadable_descriptors_attribute_start = cfs->current();
loadable_descriptors_attribute_length = attribute_length;
}
}
// Skip attribute_length for any attribute where major_verson >= JAVA_17_VERSION
Expand Down Expand Up @@ -4032,15 +4042,15 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
}
}

if (parsed_preload_attribute) {
const u2 num_classes = parse_classfile_preload_attribute(
if (parsed_loadable_descriptors_attribute) {
const u2 num_classes = parse_classfile_loadable_descriptors_attribute(
cfs,
preload_attribute_start,
loadable_descriptors_attribute_start,
CHECK);
if (_need_verify) {
guarantee_property(
preload_attribute_length == sizeof(num_classes) + sizeof(u2) * num_classes,
"Wrong Preload attribute length in class file %s", CHECK);
loadable_descriptors_attribute_length == sizeof(num_classes) + sizeof(u2) * num_classes,
"Wrong LoadableDescriptors attribute length in class file %s", CHECK);
}
}

Expand Down Expand Up @@ -4109,7 +4119,7 @@ void ClassFileParser::apply_parsed_class_metadata(
this_klass->set_inner_classes(_inner_classes);
this_klass->set_nest_members(_nest_members);
this_klass->set_nest_host_index(_nest_host);
this_klass->set_preload_classes(_preload_classes);
this_klass->set_loadable_descriptors(_loadable_descriptors);
this_klass->set_annotations(_combined_annotations);
this_klass->set_permitted_subclasses(_permitted_subclasses);
this_klass->set_record_components(_record_components);
Expand Down Expand Up @@ -5044,10 +5054,10 @@ bool ClassFileParser::verify_unqualified_name(const char* name,
return true;
}

bool ClassFileParser::is_class_in_preload_attribute(Symbol *klass) {
if (_preload_classes == nullptr) return false;
for (int i = 0; i < _preload_classes->length(); i++) {
Symbol* class_name = _cp->klass_at_noresolve(_preload_classes->at(i));
bool ClassFileParser::is_class_in_loadable_descriptors_attribute(Symbol *klass) {
if (_loadable_descriptors == nullptr) return false;
for (int i = 0; i < _loadable_descriptors->length(); i++) {
Symbol* class_name = _cp->symbol_at(_loadable_descriptors->at(i));
if (class_name == klass) return true;
}
return false;
Expand Down Expand Up @@ -5318,6 +5328,16 @@ void ClassFileParser::verify_legal_method_name(const Symbol* name, TRAPS) const
}
}

bool ClassFileParser::legal_field_signature(const Symbol* signature, TRAPS) const {
const char* const bytes = (const char*)signature->bytes();
const unsigned int length = signature->utf8_length();
const char* const p = skip_over_field_signature(bytes, false, length, CHECK_false);

if (p == nullptr || (p - bytes) != (int)length) {
return false;
}
return true;
}

// Checks if signature is a legal field signature.
void ClassFileParser::verify_legal_field_signature(const Symbol* name,
Expand Down Expand Up @@ -5593,7 +5613,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
assert(nullptr == _methods, "invariant");
assert(nullptr == _inner_classes, "invariant");
assert(nullptr == _nest_members, "invariant");
assert(nullptr == _preload_classes, "invariant");
assert(nullptr == _loadable_descriptors, "invariant");
assert(nullptr == _combined_annotations, "invariant");
assert(nullptr == _record_components, "invariant");
assert(nullptr == _permitted_subclasses, "invariant");
Expand Down Expand Up @@ -5864,7 +5884,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_nest_members(nullptr),
_nest_host(0),
_permitted_subclasses(nullptr),
_preload_classes(nullptr),
_loadable_descriptors(nullptr),
_record_components(nullptr),
_local_interfaces(nullptr),
_local_interface_indexes(nullptr),
Expand Down Expand Up @@ -5967,7 +5987,7 @@ void ClassFileParser::clear_class_metadata() {
_inner_classes = nullptr;
_nest_members = nullptr;
_permitted_subclasses = nullptr;
_preload_classes = nullptr;
_loadable_descriptors = nullptr;
_combined_annotations = nullptr;
_class_annotations = _class_type_annotations = nullptr;
_fields_annotations = _fields_type_annotations = nullptr;
Expand Down Expand Up @@ -6022,8 +6042,8 @@ ClassFileParser::~ClassFileParser() {
MetadataFactory::free_array<u2>(_loader_data, _permitted_subclasses);
}

if (_preload_classes != nullptr && _preload_classes != Universe::the_empty_short_array()) {
MetadataFactory::free_array<u2>(_loader_data, _preload_classes);
if (_loadable_descriptors != nullptr && _loadable_descriptors != Universe::the_empty_short_array()) {
MetadataFactory::free_array<u2>(_loader_data, _loadable_descriptors);
}

// Free interfaces
Expand Down Expand Up @@ -6544,20 +6564,20 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
// Preloading classes for nullable fields that are listed in the Preload attribute
// Those classes would be required later for the flattening of nullable inline type fields
TempNewSymbol name = Signature::strip_envelope(sig);
if (name != _class_name && is_class_in_preload_attribute(name)) {
log_info(class, preload)("Preloading class %s during loading of class %s. Cause: field type in Preload attribute", name->as_C_string(), _class_name->as_C_string());
if (name != _class_name && is_class_in_loadable_descriptors_attribute(sig)) {
log_info(class, preload)("Preloading class %s during loading of class %s. Cause: field type in LoadableDescriptors attribute", name->as_C_string(), _class_name->as_C_string());
oop loader = loader_data()->class_loader();
Klass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, name, Handle(THREAD, loader), _protection_domain, false, THREAD);
if (klass != nullptr) {
if (klass->is_inline_klass()) {
_inline_type_field_klasses->at_put(fieldinfo.index(), InlineKlass::cast(klass));
log_info(class, preload)("Preloading of class %s during loading of class %s (cause: field type in Preload attribute) succeeded", name->as_C_string(), _class_name->as_C_string());
log_info(class, preload)("Preloading of class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) succeeded", name->as_C_string(), _class_name->as_C_string());
} else {
// Non value class are allowed by the current spec, but it could be an indication of an issue so let's log a warning
log_warning(class, preload)("Preloading class %s during loading of class %s (cause: field type in Preload attribute) but loaded class is not a value class", name->as_C_string(), _class_name->as_C_string());
log_warning(class, preload)("Preloading class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) but loaded class is not a value class", name->as_C_string(), _class_name->as_C_string());
}
} else {
log_warning(class, preload)("Preloading of class %s during loading of class %s (cause: field type in Preload attribute) failed : %s",
log_warning(class, preload)("Preloading of class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) failed : %s",
name->as_C_string(), _class_name->as_C_string(), PENDING_EXCEPTION->klass()->name()->as_C_string());
}
// Loads triggered by the preload attribute are speculative, failures must not impact loading of current class
Expand Down
8 changes: 5 additions & 3 deletions src/hotspot/share/classfile/classFileParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class ClassFileParser {
Array<u2>* _nest_members;
u2 _nest_host;
Array<u2>* _permitted_subclasses;
Array<u2>* _preload_classes;
Array<u2>* _loadable_descriptors;
Array<RecordComponent*>* _record_components;
Array<InstanceKlass*>* _local_interfaces;
GrowableArray<u2>* _local_interface_indexes;
Expand Down Expand Up @@ -356,7 +356,7 @@ class ClassFileParser {
const u1* const permitted_subclasses_attribute_start,
TRAPS);

u2 parse_classfile_preload_attribute(const ClassFileStream* const cfs,
u2 parse_classfile_loadable_descriptors_attribute(const ClassFileStream* const cfs,
const u1* const preload_attribute_start,
TRAPS);

Expand Down Expand Up @@ -493,6 +493,8 @@ class ClassFileParser {
void verify_legal_field_name(const Symbol* name, TRAPS) const;
void verify_legal_method_name(const Symbol* name, TRAPS) const;

bool legal_field_signature(const Symbol* signature, TRAPS) const;

void verify_legal_field_signature(const Symbol* fieldname,
const Symbol* signature,
TRAPS) const;
Expand Down Expand Up @@ -617,7 +619,7 @@ class ClassFileParser {

bool is_internal() const { return INTERNAL == _pub_level; }

bool is_class_in_preload_attribute(Symbol *klass);
bool is_class_in_loadable_descriptors_attribute(Symbol *klass);

static bool verify_unqualified_name(const char* name, unsigned int length, int type);

Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/classfile/systemDictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
}
} else if (Signature::has_envelope(sig)) {
TempNewSymbol name = Signature::strip_envelope(sig);
if (name != ik->name() && ik->is_class_in_preload_attribute(name)) {
if (name != ik->name() && ik->is_class_in_loadable_descriptors_attribute(name)) {
Klass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name,
class_loader, protection_domain, false, THREAD);
if (HAS_PENDING_EXCEPTION) {
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/classfile/vmSymbols.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class SerializeClosure;
template(tag_inner_classes, "InnerClasses") \
template(tag_nest_members, "NestMembers") \
template(tag_nest_host, "NestHost") \
template(tag_preload, "Preload") \
template(tag_loadable_descriptors, "LoadableDescriptors") \
template(tag_constant_value, "ConstantValue") \
template(tag_code, "Code") \
template(tag_exceptions, "Exceptions") \
Expand Down
Loading

0 comments on commit 624c50b

Please sign in to comment.