comparison src/share/vm/classfile/classFileParser.cpp @ 1586:086d73ccd6c0

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
author kamg
date Thu, 27 May 2010 17:06:39 -0400
parents df736661d0c8
children 3a9de63b2209
comparison
equal deleted inserted replaced
1561:3548f3198dca 1586:086d73ccd6c0
23 */ 23 */
24 24
25 #include "incls/_precompiled.incl" 25 #include "incls/_precompiled.incl"
26 #include "incls/_classFileParser.cpp.incl" 26 #include "incls/_classFileParser.cpp.incl"
27 27
28 // We generally try to create the oops directly when parsing, rather than allocating 28 // We generally try to create the oops directly when parsing, rather than
29 // temporary data structures and copying the bytes twice. A temporary area is only 29 // allocating temporary data structures and copying the bytes twice. A
30 // needed when parsing utf8 entries in the constant pool and when parsing line number 30 // temporary area is only needed when parsing utf8 entries in the constant
31 // tables. 31 // pool and when parsing line number tables.
32 32
33 // We add assert in debug mode when class format is not checked. 33 // We add assert in debug mode when class format is not checked.
34 34
35 #define JAVA_CLASSFILE_MAGIC 0xCAFEBABE 35 #define JAVA_CLASSFILE_MAGIC 0xCAFEBABE
36 #define JAVA_MIN_SUPPORTED_VERSION 45 36 #define JAVA_MIN_SUPPORTED_VERSION 45
44 44
45 // Used for backward compatibility reasons: 45 // Used for backward compatibility reasons:
46 // - to check for javac bug fixes that happened after 1.5 46 // - to check for javac bug fixes that happened after 1.5
47 // - also used as the max version when running in jdk6 47 // - also used as the max version when running in jdk6
48 #define JAVA_6_VERSION 50 48 #define JAVA_6_VERSION 50
49
50 // Used for backward compatibility reasons:
51 // - to check NameAndType_info signatures more aggressively
52 #define JAVA_7_VERSION 51
49 53
50 54
51 void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) { 55 void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) {
52 // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize 56 // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
53 // this function (_current can be allocated in a register, with scalar 57 // this function (_current can be allocated in a register, with scalar
382 symbolHandle class_name(THREAD, cp->unresolved_klass_at(index)); 386 symbolHandle class_name(THREAD, cp->unresolved_klass_at(index));
383 // check the name, even if _cp_patches will overwrite it 387 // check the name, even if _cp_patches will overwrite it
384 verify_legal_class_name(class_name, CHECK_(nullHandle)); 388 verify_legal_class_name(class_name, CHECK_(nullHandle));
385 break; 389 break;
386 } 390 }
391 case JVM_CONSTANT_NameAndType: {
392 if (_need_verify && _major_version >= JAVA_7_VERSION) {
393 int sig_index = cp->signature_ref_index_at(index);
394 int name_index = cp->name_ref_index_at(index);
395 symbolHandle name(THREAD, cp->symbol_at(name_index));
396 symbolHandle sig(THREAD, cp->symbol_at(sig_index));
397 if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) {
398 verify_legal_method_signature(name, sig, CHECK_(nullHandle));
399 } else {
400 verify_legal_field_signature(name, sig, CHECK_(nullHandle));
401 }
402 }
403 break;
404 }
387 case JVM_CONSTANT_Fieldref: 405 case JVM_CONSTANT_Fieldref:
388 case JVM_CONSTANT_Methodref: 406 case JVM_CONSTANT_Methodref:
389 case JVM_CONSTANT_InterfaceMethodref: { 407 case JVM_CONSTANT_InterfaceMethodref: {
390 int name_and_type_ref_index = cp->name_and_type_ref_index_at(index); 408 int name_and_type_ref_index = cp->name_and_type_ref_index_at(index);
391 // already verified to be utf8 409 // already verified to be utf8
394 int signature_ref_index = cp->signature_ref_index_at(name_and_type_ref_index); 412 int signature_ref_index = cp->signature_ref_index_at(name_and_type_ref_index);
395 symbolHandle name(THREAD, cp->symbol_at(name_ref_index)); 413 symbolHandle name(THREAD, cp->symbol_at(name_ref_index));
396 symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index)); 414 symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index));
397 if (tag == JVM_CONSTANT_Fieldref) { 415 if (tag == JVM_CONSTANT_Fieldref) {
398 verify_legal_field_name(name, CHECK_(nullHandle)); 416 verify_legal_field_name(name, CHECK_(nullHandle));
399 verify_legal_field_signature(name, signature, CHECK_(nullHandle)); 417 if (_need_verify && _major_version >= JAVA_7_VERSION) {
418 // Signature is verified above, when iterating NameAndType_info.
419 // Need only to be sure it's the right type.
420 if (signature->byte_at(0) == JVM_SIGNATURE_FUNC) {
421 throwIllegalSignature(
422 "Field", name, signature, CHECK_(nullHandle));
423 }
424 } else {
425 verify_legal_field_signature(name, signature, CHECK_(nullHandle));
426 }
400 } else { 427 } else {
401 verify_legal_method_name(name, CHECK_(nullHandle)); 428 verify_legal_method_name(name, CHECK_(nullHandle));
402 verify_legal_method_signature(name, signature, CHECK_(nullHandle)); 429 if (_need_verify && _major_version >= JAVA_7_VERSION) {
430 // Signature is verified above, when iterating NameAndType_info.
431 // Need only to be sure it's the right type.
432 if (signature->byte_at(0) != JVM_SIGNATURE_FUNC) {
433 throwIllegalSignature(
434 "Method", name, signature, CHECK_(nullHandle));
435 }
436 } else {
437 verify_legal_method_signature(name, signature, CHECK_(nullHandle));
438 }
403 if (tag == JVM_CONSTANT_Methodref) { 439 if (tag == JVM_CONSTANT_Methodref) {
404 // 4509014: If a class method name begins with '<', it must be "<init>". 440 // 4509014: If a class method name begins with '<', it must be "<init>".
405 assert(!name.is_null(), "method name in constant pool is null"); 441 assert(!name.is_null(), "method name in constant pool is null");
406 unsigned int name_len = name->utf8_length(); 442 unsigned int name_len = name->utf8_length();
407 assert(name_len > 0, "bad method name"); // already verified as legal name 443 assert(name_len > 0, "bad method name"); // already verified as legal name
1311 "Exceptions attribute has wrong length in class file %s", CHECK_NULL); 1347 "Exceptions attribute has wrong length in class file %s", CHECK_NULL);
1312 } 1348 }
1313 return checked_exceptions_start; 1349 return checked_exceptions_start;
1314 } 1350 }
1315 1351
1352 void ClassFileParser::throwIllegalSignature(
1353 const char* type, symbolHandle name, symbolHandle sig, TRAPS) {
1354 ResourceMark rm(THREAD);
1355 Exceptions::fthrow(THREAD_AND_LOCATION,
1356 vmSymbols::java_lang_ClassFormatError(),
1357 "%s \"%s\" in class %s has illegal signature \"%s\"", type,
1358 name->as_C_string(), _class_name->as_C_string(), sig->as_C_string());
1359 }
1316 1360
1317 #define MAX_ARGS_SIZE 255 1361 #define MAX_ARGS_SIZE 255
1318 #define MAX_CODE_SIZE 65535 1362 #define MAX_CODE_SIZE 65535
1319 #define INITIAL_MAX_LVT_NUMBER 256 1363 #define INITIAL_MAX_LVT_NUMBER 256
1320 1364
4056 char* bytes = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); 4100 char* bytes = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
4057 unsigned int length = signature->utf8_length(); 4101 unsigned int length = signature->utf8_length();
4058 char* p = skip_over_field_signature(bytes, false, length, CHECK); 4102 char* p = skip_over_field_signature(bytes, false, length, CHECK);
4059 4103
4060 if (p == NULL || (p - bytes) != (int)length) { 4104 if (p == NULL || (p - bytes) != (int)length) {
4061 ResourceMark rm(THREAD); 4105 throwIllegalSignature("Field", name, signature, CHECK);
4062 Exceptions::fthrow(
4063 THREAD_AND_LOCATION,
4064 vmSymbolHandles::java_lang_ClassFormatError(),
4065 "Field \"%s\" in class %s has illegal signature \"%s\"",
4066 name->as_C_string(), _class_name->as_C_string(), bytes
4067 );
4068 return;
4069 } 4106 }
4070 } 4107 }
4071 4108
4072 // Checks if signature is a legal method signature. 4109 // Checks if signature is a legal method signature.
4073 // Returns number of parameters 4110 // Returns number of parameters
4114 } 4151 }
4115 } 4152 }
4116 } 4153 }
4117 } 4154 }
4118 // Report error 4155 // Report error
4119 ResourceMark rm(THREAD); 4156 throwIllegalSignature("Method", name, signature, CHECK_0);
4120 Exceptions::fthrow(
4121 THREAD_AND_LOCATION,
4122 vmSymbolHandles::java_lang_ClassFormatError(),
4123 "Method \"%s\" in class %s has illegal signature \"%s\"",
4124 name->as_C_string(), _class_name->as_C_string(), p
4125 );
4126 return 0; 4157 return 0;
4127 } 4158 }
4128 4159
4129 4160
4130 // Unqualified names may not contain the characters '.', ';', or '/'. 4161 // Unqualified names may not contain the characters '.', ';', or '/'.