提交 db7077c0 编写于 作者: K kamg

6930553: classfile format checker allows invalid method descriptor in...

6930553: classfile format checker allows invalid method descriptor in CONSTANT_NameAndType_info in some cases
Summary: Check NameAndType_info signatures aggressively, even when unreferenced
Reviewed-by: coleenp, acorn, never
上级 c901506a
...@@ -25,10 +25,10 @@ ...@@ -25,10 +25,10 @@
#include "incls/_precompiled.incl" #include "incls/_precompiled.incl"
#include "incls/_classFileParser.cpp.incl" #include "incls/_classFileParser.cpp.incl"
// We generally try to create the oops directly when parsing, rather than allocating // We generally try to create the oops directly when parsing, rather than
// temporary data structures and copying the bytes twice. A temporary area is only // allocating temporary data structures and copying the bytes twice. A
// needed when parsing utf8 entries in the constant pool and when parsing line number // temporary area is only needed when parsing utf8 entries in the constant
// tables. // pool and when parsing line number tables.
// We add assert in debug mode when class format is not checked. // We add assert in debug mode when class format is not checked.
...@@ -47,6 +47,10 @@ ...@@ -47,6 +47,10 @@
// - also used as the max version when running in jdk6 // - also used as the max version when running in jdk6
#define JAVA_6_VERSION 50 #define JAVA_6_VERSION 50
// Used for backward compatibility reasons:
// - to check NameAndType_info signatures more aggressively
#define JAVA_7_VERSION 51
void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) { void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
...@@ -384,6 +388,20 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { ...@@ -384,6 +388,20 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
verify_legal_class_name(class_name, CHECK_(nullHandle)); verify_legal_class_name(class_name, CHECK_(nullHandle));
break; break;
} }
case JVM_CONSTANT_NameAndType: {
if (_need_verify && _major_version >= JAVA_7_VERSION) {
int sig_index = cp->signature_ref_index_at(index);
int name_index = cp->name_ref_index_at(index);
symbolHandle name(THREAD, cp->symbol_at(name_index));
symbolHandle sig(THREAD, cp->symbol_at(sig_index));
if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) {
verify_legal_method_signature(name, sig, CHECK_(nullHandle));
} else {
verify_legal_field_signature(name, sig, CHECK_(nullHandle));
}
}
break;
}
case JVM_CONSTANT_Fieldref: case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref: case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_InterfaceMethodref: { case JVM_CONSTANT_InterfaceMethodref: {
...@@ -396,10 +414,28 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { ...@@ -396,10 +414,28 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index)); symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index));
if (tag == JVM_CONSTANT_Fieldref) { if (tag == JVM_CONSTANT_Fieldref) {
verify_legal_field_name(name, CHECK_(nullHandle)); verify_legal_field_name(name, CHECK_(nullHandle));
verify_legal_field_signature(name, signature, CHECK_(nullHandle)); if (_need_verify && _major_version >= JAVA_7_VERSION) {
// Signature is verified above, when iterating NameAndType_info.
// Need only to be sure it's the right type.
if (signature->byte_at(0) == JVM_SIGNATURE_FUNC) {
throwIllegalSignature(
"Field", name, signature, CHECK_(nullHandle));
}
} else {
verify_legal_field_signature(name, signature, CHECK_(nullHandle));
}
} else { } else {
verify_legal_method_name(name, CHECK_(nullHandle)); verify_legal_method_name(name, CHECK_(nullHandle));
verify_legal_method_signature(name, signature, CHECK_(nullHandle)); if (_need_verify && _major_version >= JAVA_7_VERSION) {
// Signature is verified above, when iterating NameAndType_info.
// Need only to be sure it's the right type.
if (signature->byte_at(0) != JVM_SIGNATURE_FUNC) {
throwIllegalSignature(
"Method", name, signature, CHECK_(nullHandle));
}
} else {
verify_legal_method_signature(name, signature, CHECK_(nullHandle));
}
if (tag == JVM_CONSTANT_Methodref) { if (tag == JVM_CONSTANT_Methodref) {
// 4509014: If a class method name begins with '<', it must be "<init>". // 4509014: If a class method name begins with '<', it must be "<init>".
assert(!name.is_null(), "method name in constant pool is null"); assert(!name.is_null(), "method name in constant pool is null");
...@@ -1313,6 +1349,14 @@ u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length, ...@@ -1313,6 +1349,14 @@ u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length,
return checked_exceptions_start; return checked_exceptions_start;
} }
void ClassFileParser::throwIllegalSignature(
const char* type, symbolHandle name, symbolHandle sig, TRAPS) {
ResourceMark rm(THREAD);
Exceptions::fthrow(THREAD_AND_LOCATION,
vmSymbols::java_lang_ClassFormatError(),
"%s \"%s\" in class %s has illegal signature \"%s\"", type,
name->as_C_string(), _class_name->as_C_string(), sig->as_C_string());
}
#define MAX_ARGS_SIZE 255 #define MAX_ARGS_SIZE 255
#define MAX_CODE_SIZE 65535 #define MAX_CODE_SIZE 65535
...@@ -4058,14 +4102,7 @@ void ClassFileParser::verify_legal_field_signature(symbolHandle name, symbolHand ...@@ -4058,14 +4102,7 @@ void ClassFileParser::verify_legal_field_signature(symbolHandle name, symbolHand
char* p = skip_over_field_signature(bytes, false, length, CHECK); char* p = skip_over_field_signature(bytes, false, length, CHECK);
if (p == NULL || (p - bytes) != (int)length) { if (p == NULL || (p - bytes) != (int)length) {
ResourceMark rm(THREAD); throwIllegalSignature("Field", name, signature, CHECK);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbolHandles::java_lang_ClassFormatError(),
"Field \"%s\" in class %s has illegal signature \"%s\"",
name->as_C_string(), _class_name->as_C_string(), bytes
);
return;
} }
} }
...@@ -4116,13 +4153,7 @@ int ClassFileParser::verify_legal_method_signature(symbolHandle name, symbolHand ...@@ -4116,13 +4153,7 @@ int ClassFileParser::verify_legal_method_signature(symbolHandle name, symbolHand
} }
} }
// Report error // Report error
ResourceMark rm(THREAD); throwIllegalSignature("Method", name, signature, CHECK_0);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbolHandles::java_lang_ClassFormatError(),
"Method \"%s\" in class %s has illegal signature \"%s\"",
name->as_C_string(), _class_name->as_C_string(), p
);
return 0; return 0;
} }
......
...@@ -195,6 +195,9 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -195,6 +195,9 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
if (!b) { classfile_parse_error(msg, index, name, CHECK); } if (!b) { classfile_parse_error(msg, index, name, CHECK); }
} }
void throwIllegalSignature(
const char* type, symbolHandle name, symbolHandle sig, TRAPS);
bool is_supported_version(u2 major, u2 minor); bool is_supported_version(u2 major, u2 minor);
bool has_illegal_visibility(jint flags); bool has_illegal_visibility(jint flags);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册