8161224: CONSTANT_NameAndType_info permits references to illegal names and descriptors
Enforces proper format checking for NameAndType string content, and that the checking occurs even when not referenced in classfile Reviewed-by: coleenp, hseigel, ddmitriev
This commit is contained in:
parent
d4728727fb
commit
a8147854b7
@ -95,7 +95,6 @@
|
||||
#define JAVA_6_VERSION 50
|
||||
|
||||
// Used for backward compatibility reasons:
|
||||
// - to check NameAndType_info signatures more aggressively
|
||||
// - to disallow argument and require ACC_STATIC for <clinit> methods
|
||||
#define JAVA_7_VERSION 51
|
||||
|
||||
@ -564,7 +563,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
||||
break;
|
||||
}
|
||||
case JVM_CONSTANT_NameAndType: {
|
||||
if (_need_verify && _major_version >= JAVA_7_VERSION) {
|
||||
if (_need_verify) {
|
||||
const int sig_index = cp->signature_ref_index_at(index);
|
||||
const int name_index = cp->name_ref_index_at(index);
|
||||
const Symbol* const name = cp->symbol_at(name_index);
|
||||
@ -572,9 +571,17 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
||||
guarantee_property(sig->utf8_length() != 0,
|
||||
"Illegal zero length constant pool entry at %d in class %s",
|
||||
sig_index, CHECK);
|
||||
guarantee_property(name->utf8_length() != 0,
|
||||
"Illegal zero length constant pool entry at %d in class %s",
|
||||
name_index, CHECK);
|
||||
|
||||
if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) {
|
||||
// Format check method name and signature
|
||||
verify_legal_method_name(name, CHECK);
|
||||
verify_legal_method_signature(name, sig, CHECK);
|
||||
} else {
|
||||
// Format check field name and signature
|
||||
verify_legal_field_name(name, CHECK);
|
||||
verify_legal_field_signature(name, sig, CHECK);
|
||||
}
|
||||
}
|
||||
@ -595,42 +602,32 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
||||
const Symbol* const name = cp->symbol_at(name_ref_index);
|
||||
const Symbol* const signature = cp->symbol_at(signature_ref_index);
|
||||
if (tag == JVM_CONSTANT_Fieldref) {
|
||||
verify_legal_field_name(name, CHECK);
|
||||
if (_need_verify && _major_version >= JAVA_7_VERSION) {
|
||||
// Signature is verified above, when iterating NameAndType_info.
|
||||
// Need only to be sure it's non-zero length and the right type.
|
||||
if (_need_verify) {
|
||||
// Field name and signature are verified above, when iterating NameAndType_info.
|
||||
// Need only to be sure signature is non-zero length and the right type.
|
||||
if (signature->utf8_length() == 0 ||
|
||||
signature->byte_at(0) == JVM_SIGNATURE_FUNC) {
|
||||
throwIllegalSignature(
|
||||
"Field", name, signature, CHECK);
|
||||
throwIllegalSignature("Field", name, signature, CHECK);
|
||||
}
|
||||
} else {
|
||||
verify_legal_field_signature(name, signature, CHECK);
|
||||
}
|
||||
} else {
|
||||
verify_legal_method_name(name, CHECK);
|
||||
if (_need_verify && _major_version >= JAVA_7_VERSION) {
|
||||
// Signature is verified above, when iterating NameAndType_info.
|
||||
// Need only to be sure it's non-zero length and the right type.
|
||||
if (_need_verify) {
|
||||
// Method name and signature are verified above, when iterating NameAndType_info.
|
||||
// Need only to be sure signature is non-zero length and the right type.
|
||||
if (signature->utf8_length() == 0 ||
|
||||
signature->byte_at(0) != JVM_SIGNATURE_FUNC) {
|
||||
throwIllegalSignature(
|
||||
"Method", name, signature, CHECK);
|
||||
throwIllegalSignature("Method", name, signature, CHECK);
|
||||
}
|
||||
} else {
|
||||
verify_legal_method_signature(name, signature, CHECK);
|
||||
}
|
||||
if (tag == JVM_CONSTANT_Methodref) {
|
||||
// 4509014: If a class method name begins with '<', it must be "<init>".
|
||||
assert(name != NULL, "method name in constant pool is null");
|
||||
const unsigned int name_len = name->utf8_length();
|
||||
if (name_len != 0 && name->byte_at(0) == '<') {
|
||||
if (name != vmSymbols::object_initializer_name()) {
|
||||
classfile_parse_error(
|
||||
"Bad method name at constant pool index %u in class file %s",
|
||||
name_ref_index, CHECK);
|
||||
}
|
||||
}
|
||||
// 4509014: If a class method name begins with '<', it must be "<init>"
|
||||
const unsigned int name_len = name->utf8_length();
|
||||
if (tag == JVM_CONSTANT_Methodref &&
|
||||
name_len != 0 &&
|
||||
name->byte_at(0) == '<' &&
|
||||
name != vmSymbols::object_initializer_name()) {
|
||||
classfile_parse_error(
|
||||
"Bad method name at constant pool index %u in class file %s",
|
||||
name_ref_index, CHECK);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -4843,19 +4840,28 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature,
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 4900761: For class version > 48, any unicode is allowed in class name.
|
||||
// Skip leading 'L' and ignore first appearance of ';'
|
||||
length--;
|
||||
signature++;
|
||||
while (length > 0 && signature[0] != ';') {
|
||||
if (signature[0] == '.') {
|
||||
classfile_parse_error("Class name contains illegal character '.' in descriptor in class file %s", CHECK_0);
|
||||
}
|
||||
length--;
|
||||
signature++;
|
||||
}
|
||||
if (signature[0] == ';') { return signature + 1; }
|
||||
}
|
||||
char* c = strchr((char*) signature, ';');
|
||||
// Format check signature
|
||||
if (c != NULL) {
|
||||
ResourceMark rm(THREAD);
|
||||
int newlen = c - (char*) signature;
|
||||
char* sig = NEW_RESOURCE_ARRAY(char, newlen + 1);
|
||||
strncpy(sig, signature, newlen);
|
||||
sig[newlen] = '\0';
|
||||
|
||||
bool legal = verify_unqualified_name(sig, newlen, LegalClass);
|
||||
if (!legal) {
|
||||
classfile_parse_error("Class name contains illegal character "
|
||||
"in descriptor in class file %s",
|
||||
CHECK_0);
|
||||
return NULL;
|
||||
}
|
||||
return signature + newlen + 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
case JVM_SIGNATURE_ARRAY:
|
||||
@ -4869,7 +4875,6 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature,
|
||||
length--;
|
||||
void_ok = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user