Mercurial > hg > graal-jvmci-8
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 '/'. |