src/share/vm/classfile/classFileParser.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/classfile/classFileParser.cpp

src/share/vm/classfile/classFileParser.cpp

Print this page
rev 1449 : 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:

*** 23,36 **** */ #include "incls/_precompiled.incl" #include "incls/_classFileParser.cpp.incl" ! // We generally try to create the oops directly when parsing, rather than allocating ! // temporary data structures and copying the bytes twice. A temporary area is only ! // needed when parsing utf8 entries in the constant pool and when parsing line number ! // tables. // We add assert in debug mode when class format is not checked. #define JAVA_CLASSFILE_MAGIC 0xCAFEBABE #define JAVA_MIN_SUPPORTED_VERSION 45 --- 23,36 ---- */ #include "incls/_precompiled.incl" #include "incls/_classFileParser.cpp.incl" ! // We generally try to create the oops directly when parsing, rather than ! // allocating temporary data structures and copying the bytes twice. A ! // temporary area is only needed when parsing utf8 entries in the constant ! // pool and when parsing line number tables. // We add assert in debug mode when class format is not checked. #define JAVA_CLASSFILE_MAGIC 0xCAFEBABE #define JAVA_MIN_SUPPORTED_VERSION 45
*** 45,55 **** --- 45,59 ---- // Used for backward compatibility reasons: // - to check for javac bug fixes that happened after 1.5 // - also used as the max version when running in jdk6 #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) { // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize // this function (_current can be allocated in a register, with scalar // replacement of aggregates). The _current pointer is copied back to // stream() when this function returns. DON'T call another method within
*** 382,391 **** --- 386,409 ---- symbolHandle class_name(THREAD, cp->unresolved_klass_at(index)); // check the name, even if _cp_patches will overwrite it verify_legal_class_name(class_name, CHECK_(nullHandle)); 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_Methodref: case JVM_CONSTANT_InterfaceMethodref: { int name_and_type_ref_index = cp->name_and_type_ref_index_at(index); // already verified to be utf8
*** 394,407 **** --- 412,443 ---- int signature_ref_index = cp->signature_ref_index_at(name_and_type_ref_index); symbolHandle name(THREAD, cp->symbol_at(name_ref_index)); symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index)); if (tag == JVM_CONSTANT_Fieldref) { verify_legal_field_name(name, 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 { verify_legal_method_name(name, 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) { // 4509014: If a class method name begins with '<', it must be "<init>". assert(!name.is_null(), "method name in constant pool is null"); unsigned int name_len = name->utf8_length(); assert(name_len > 0, "bad method name"); // already verified as legal name
*** 1311,1320 **** --- 1347,1364 ---- "Exceptions attribute has wrong length in class file %s", CHECK_NULL); } 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_CODE_SIZE 65535 #define INITIAL_MAX_LVT_NUMBER 256
*** 4056,4073 **** char* bytes = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); unsigned int length = signature->utf8_length(); char* p = skip_over_field_signature(bytes, false, length, CHECK); if (p == NULL || (p - bytes) != (int)length) { ! ResourceMark rm(THREAD); ! 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; } } // Checks if signature is a legal method signature. // Returns number of parameters --- 4100,4110 ---- char* bytes = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); unsigned int length = signature->utf8_length(); char* p = skip_over_field_signature(bytes, false, length, CHECK); if (p == NULL || (p - bytes) != (int)length) { ! throwIllegalSignature("Field", name, signature, CHECK); } } // Checks if signature is a legal method signature. // Returns number of parameters
*** 4114,4130 **** } } } } // Report error ! ResourceMark rm(THREAD); ! 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; } // Unqualified names may not contain the characters '.', ';', or '/'. --- 4151,4161 ---- } } } } // Report error ! throwIllegalSignature("Method", name, signature, CHECK_0); return 0; } // Unqualified names may not contain the characters '.', ';', or '/'.
src/share/vm/classfile/classFileParser.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File