in vm/vmcore/src/class_support/Class_File_Loader.cpp [2503:2706]
bool ConstantPool::check(Global_Env* env, Class* clss, bool is_trusted_cl)
{
for(unsigned i = 1; i < m_size; i++) {
switch(unsigned char tag = get_tag(i))
{
case CONSTANT_Class:
{
unsigned name_index = get_class_name_index(i);
if (!valid_cpi(clss, name_index, CONSTANT_Utf8, "for class name at CONSTANT_Class entry")) {
// illegal name index
return false;
}
if(!check_class_name(get_utf8_string(name_index)->bytes, get_utf8_string(name_index)->len,
clss->get_version() < JAVA5_CLASS_FILE_VERSION))
{
REPORT_FAILED_CLASS_FORMAT(clss," illegal CONSTANT_Class name "
<< "\"" << get_utf8_string(name_index)->bytes << "\"");
return false;
}
break;
}
case CONSTANT_Methodref:
case CONSTANT_Fieldref:
case CONSTANT_InterfaceMethodref:
{
unsigned class_index = get_ref_class_index(i);
if (!valid_cpi(clss, class_index, CONSTANT_Class, "for class name at CONSTANT_*ref entry")) {
return false;
}
unsigned name_type_index = get_ref_name_and_type_index(i);
if (!valid_cpi(clss, name_type_index, CONSTANT_NameAndType, "for name-and-type at CONSTANT_*ref entry")) {
return false;
}
const char *next = NULL;
String *name;
String *descriptor;
unsigned name_index = get_name_and_type_name_index(name_type_index);
if(!valid_cpi(clss, name_index, CONSTANT_Utf8, "for name at CONSTANT_*ref entry")) {
return false;
}
unsigned descriptor_index = get_name_and_type_descriptor_index(name_type_index);
if (!valid_cpi(clss, descriptor_index, CONSTANT_Utf8, "for descriptor at CONSTANT_*ref entry")) {
return false;
}
name = get_utf8_string(name_index);
descriptor = get_utf8_string(descriptor_index);
if(tag == CONSTANT_Methodref)
{
//check method name
if(is_trusted_cl) {
if(env->verify_all && (name != env->Init_String)
&& !is_valid_member_name(name->bytes,name->len, clss->get_version() < JAVA5_CLASS_FILE_VERSION, true))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal method name for CONSTANT_Methodref entry: " << name->bytes);
return false;
}
if(name->bytes[0] == '<' && name != env->Init_String) {
REPORT_FAILED_CLASS_FORMAT(clss, " illegal method name "<< name->bytes
<< " at constant pool index " << name_index);
return false;
}
} else { //always check method name if classloader is not system
if((name != env->Init_String)
&& !is_valid_member_name(name->bytes,name->len, clss->get_version() < JAVA5_CLASS_FILE_VERSION, true))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal method name for CONSTANT_Methodref entry: "
<< name->bytes);
return false;
}
}
//check method descriptor
if(!check_method_descriptor(descriptor->bytes, clss->get_version() < JAVA5_CLASS_FILE_VERSION))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal method descriptor at CONSTANT_Methodref entry: "
<< descriptor->bytes);
return false;
}
//for <init> method return type must be void
//See specification 4.5.2
if(name == env->Init_String)
{
if(descriptor->bytes[descriptor->len - 1] != 'V')
{
REPORT_FAILED_CLASS_FORMAT(clss, " return type of <init> method"
" is not void at CONSTANT_Methodref entry");
return false;
}
}
}
if(tag == CONSTANT_Fieldref)
{
//check field name
if(is_trusted_cl) {
if(env->verify_all && !is_valid_member_name(name->bytes, name->len,
clss->get_version() < JAVA5_CLASS_FILE_VERSION, false))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal field name for CONSTANT_Filedref entry: "
<< name->bytes);
return false;
}
} else {
if(!is_valid_member_name(name->bytes, name->len,
clss->get_version() < JAVA5_CLASS_FILE_VERSION, false))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal field name for CONSTANT_Filedref entry: "
<< name->bytes);
return false;
}
}
//check field descriptor
if(!is_valid_member_descriptor(descriptor->bytes, &next, false,
clss->get_version() < JAVA5_CLASS_FILE_VERSION) || *next != '\0' )
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal field descriptor at CONSTANT_Fieldref entry: "
<< descriptor->bytes);
return false;
}
}
if(tag == CONSTANT_InterfaceMethodref)
{
//check method name, name can't be <init>
//See specification 4.5.2 about name_and_type_index last sentence.
if(is_trusted_cl) {
if(env->verify_all && (name != env->Clinit_String)
&& !is_valid_member_name(name->bytes, name->len,
clss->get_version() < JAVA5_CLASS_FILE_VERSION, true))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal method name for CONSTANT_InterfaceMethod entry: "
<< name->bytes);
return false;
}
} else {
if(!is_valid_member_name(name->bytes, name->len,
clss->get_version() < JAVA5_CLASS_FILE_VERSION, true))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal method name for CONSTANT_InterfaceMethod entry: "
<< name->bytes);
return false;
}
}
//check method descriptor
if(!check_method_descriptor(descriptor->bytes, clss->get_version() < JAVA5_CLASS_FILE_VERSION))
{
REPORT_FAILED_CLASS_FORMAT(clss, " illegal method descriptor at CONSTANT_InterfaceMethodref entry: "
<< descriptor->bytes);
return false;
}
}
break;
}
case CONSTANT_String:
{
unsigned string_index = get_string_index(i);
if (!valid_cpi(clss, string_index, CONSTANT_Utf8, "for string at CONSTANT_String entry")) {
// illegal string index
return false;
}
// set entry to the actual string
resolve_entry(i, get_utf8_string(string_index));
break;
}
case CONSTANT_Integer:
case CONSTANT_Float:
// not much to do here
break;
case CONSTANT_Long:
case CONSTANT_Double:
//check Long and Double indexes, n+1 index should be valid too.
//See specification 4.5.5
if(i + 1 == m_size){
REPORT_FAILED_CLASS_FORMAT(clss, " illegal indexes for Long or Double " << i << " and " << i + 1);
return false;
}
i++;
break;
case CONSTANT_NameAndType:
{
//See specification 4.5.6
unsigned name_index = get_name_and_type_name_index(i);
unsigned descriptor_index = get_name_and_type_descriptor_index(i);
if(!valid_cpi(clss, name_index , CONSTANT_Utf8, "for name at CONSTANT_NameAndType entry")) {
return false;
}
if (!valid_cpi(clss, descriptor_index, CONSTANT_Utf8, "for descriptor at CONSTANT_NameAndType entry")) {
return false;
}
resolve_entry(i, get_utf8_string(name_index), get_utf8_string(descriptor_index));
break;
}
case CONSTANT_Utf8:
// nothing to do here
break;
default:
REPORT_FAILED_CLASS_FORMAT(clss, " wrong constant pool tag " << get_tag(i));
return false;
}
}
return true;
} // ConstantPool::check