src/share/vm/classfile/classFileParser.cpp

Print this page
rev 3 : [mq]: anonk.patch

*** 165,179 **** --- 165,191 ---- u1* utf8_buffer = cfs->get_u1_buffer(); assert(utf8_buffer != NULL, "null utf8 buffer"); // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward. cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags cfs->skip_u1_fast(utf8_length); + // Before storing the symbol, make sure it's legal if (_need_verify) { verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK); } + if (has_cp_patch_at(index)) { + Handle patch = clear_cp_patch_at(index); + guarantee_property(java_lang_String::is_instance(patch()), + "Illegal utf8 patch at %d in class file %s", + index, CHECK); + char* str = java_lang_String::as_utf8_string(patch()); + // (could use java_lang_String::as_symbol instead, but might as well batch them) + utf8_buffer = (u1*) str; + utf8_length = strlen(str); + } + unsigned int hash; symbolOop result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash); if (result == NULL) { names[names_count] = (char*)utf8_buffer; lengths[names_count] = utf8_length;
*** 298,309 **** check_property( valid_cp_range(class_index, length) && cp->tag_at(class_index).is_utf8(), "Invalid constant pool index %u in class file %s", class_index, CHECK_(nullHandle)); ! cp->unresolved_klass_at_put(index, cp->symbol_at(class_index)); } break; case JVM_CONSTANT_UnresolvedString : ShouldNotReachHere(); // Only JVM_CONSTANT_StringIndex should be present break; case JVM_CONSTANT_StringIndex : --- 310,327 ---- check_property( valid_cp_range(class_index, length) && cp->tag_at(class_index).is_utf8(), "Invalid constant pool index %u in class file %s", class_index, CHECK_(nullHandle)); ! symbolOop name = cp->symbol_at(class_index); ! klassOop wkk = SystemDictionary::find_well_known_klass(name); ! if (wkk != NULL) { ! cp->klass_at_put(index, wkk); // eagerly resolve ! } else { ! cp->unresolved_klass_at_put(index, name); } + } break; case JVM_CONSTANT_UnresolvedString : ShouldNotReachHere(); // Only JVM_CONSTANT_StringIndex should be present break; case JVM_CONSTANT_StringIndex :
*** 323,342 **** --- 341,389 ---- ShouldNotReachHere(); break; } // end of switch } // end of for + if (_cp_patches != NULL) { + // need to treat this_class specially... + int this_class_index; + { + cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len + u1* mark = cfs->current(); + u2 flags = cfs->get_u2_fast(); + this_class_index = cfs->get_u2_fast(); + cfs->set_current(mark); // revert to mark + } + + for (index = 1; index < length; index++) { // Index 0 is unused + if (has_cp_patch_at(index)) { + guarantee_property(index != this_class_index, + "Illegal constant pool patch to self at %d in class file %s", + index, CHECK_(nullHandle)); + patch_constant_pool(cp, index, cp_patch_at(index), CHECK_(nullHandle)); + } + } + // Ensure that all the patches have been used. + for (index = 0; index < _cp_patches->length(); index++) { + guarantee_property(!has_cp_patch_at(index), + "Unused constant pool patch at %d in class file %s", + index, CHECK_(nullHandle)); + } + } + if (!_need_verify) { return cp; } // second verification pass - checks the strings are of the right format. + // but not yet to the other entries for (index = 1; index < length; index++) { jbyte tag = cp->tag_at(index).value(); switch (tag) { case JVM_CONSTANT_UnresolvedClass: { 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_Fieldref: case JVM_CONSTANT_Methodref:
*** 375,384 **** --- 422,489 ---- return cp; } + void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) { + BasicType patch_type = T_VOID; + switch (cp->tag_at(index).value()) { + + case JVM_CONSTANT_UnresolvedClass : + // Patching a class means pre-resolving it. + // The name in the constant pool is ignored. + guarantee_property(java_lang_Class::is_instance(patch()) + && !java_lang_Class::is_primitive(patch()), + "Illegal class patch at %d in class file %s", + index, CHECK); + cp->klass_at_put(index, java_lang_Class::as_klassOop(patch())); + break; + + case JVM_CONSTANT_UnresolvedString : + // Patching a string means pre-resolving it. + // The spelling in the constant pool is ignored. + // The constant reference may be any object whatever. + // If it is not a real string, the constant is referred to + // as a "pseudo-string". + cp->string_at_put(index, patch()); + break; + + case JVM_CONSTANT_Integer : patch_type = T_INT; goto patch_prim; + case JVM_CONSTANT_Float : patch_type = T_FLOAT; goto patch_prim; + case JVM_CONSTANT_Long : patch_type = T_LONG; goto patch_prim; + case JVM_CONSTANT_Double : patch_type = T_DOUBLE; goto patch_prim; + patch_prim: + { + jvalue value; + BasicType value_type = java_lang_boxing_object::get_value(patch(), &value); + guarantee_property(value_type == patch_type, + "Illegal primitive patch at %d in class file %s", + index, CHECK); + switch (value_type) { + case T_INT: cp->int_at_put(index, value.i); break; + case T_FLOAT: cp->float_at_put(index, value.f); break; + case T_LONG: cp->long_at_put(index, value.j); break; + case T_DOUBLE: cp->long_at_put(index, value.d); break; + default: assert(false, ""); + } + } + break; + + default: + // %%% TODO: put method handles into CONSTANT_InterfaceMethodref, etc. + guarantee_property(!has_cp_patch_at(index), + "Illegal unexpected patch at %d in class file %s", + index, CHECK); + return; + } + + // On fall-through, mark the patch as used. + clear_cp_patch_at(index); + } + + + class NameSigHash: public ResourceObj { public: symbolOop _name; // name symbolOop _sig; // signature NameSigHash* _next; // Next entry in hash table
*** 445,459 **** objArrayHandle interfaces (THREAD, interface_oop); int index; for (index = 0; index < length; index++) { u2 interface_index = cfs->get_u2(CHECK_(nullHandle)); check_property( valid_cp_range(interface_index, cp->length()) && ! cp->tag_at(interface_index).is_unresolved_klass(), "Interface name has bad constant pool index %u in class file %s", interface_index, CHECK_(nullHandle)); symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index)); // Don't need to check legal name because it's checked when parsing constant pool. // But need to make sure it's not an array type. guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY, --- 550,568 ---- objArrayHandle interfaces (THREAD, interface_oop); int index; for (index = 0; index < length; index++) { u2 interface_index = cfs->get_u2(CHECK_(nullHandle)); + KlassHandle interf; check_property( valid_cp_range(interface_index, cp->length()) && ! cp->tag_at(interface_index).is_klass_reference(), "Interface name has bad constant pool index %u in class file %s", interface_index, CHECK_(nullHandle)); + if (cp->tag_at(interface_index).is_klass()) { + interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index)); + } else { symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index)); // Don't need to check legal name because it's checked when parsing constant pool. // But need to make sure it's not an array type. guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
*** 462,474 **** vmtimer->suspend(); // do not count recursive loading twice // Call resolve_super so classcircularity is checked klassOop k = SystemDictionary::resolve_super_or_fail(class_name, unresolved_klass, class_loader, protection_domain, false, CHECK_(nullHandle)); ! KlassHandle interf (THREAD, k); vmtimer->resume(); if (!Klass::cast(interf())->is_interface()) { THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", nullHandle); } interfaces->obj_at_put(index, interf()); } --- 571,586 ---- vmtimer->suspend(); // do not count recursive loading twice // Call resolve_super so classcircularity is checked klassOop k = SystemDictionary::resolve_super_or_fail(class_name, unresolved_klass, class_loader, protection_domain, false, CHECK_(nullHandle)); ! interf = KlassHandle(THREAD, k); vmtimer->resume(); + cp->klass_at_put(interface_index, interf()); // eagerly resolve + } + if (!Klass::cast(interf())->is_interface()) { THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", nullHandle); } interfaces->obj_at_put(index, interf()); }
*** 874,885 **** "Illegal exception table range in class file %s", CHECK_(nullHandle)); guarantee_property(handler_pc < code_length, "Illegal exception table handler in class file %s", CHECK_(nullHandle)); if (catch_type_index != 0) { guarantee_property(valid_cp_range(catch_type_index, cp->length()) && ! (cp->tag_at(catch_type_index).is_klass() || ! cp->tag_at(catch_type_index).is_unresolved_klass()), "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle)); } } exception_handlers->int_at_put(index++, start_pc); exception_handlers->int_at_put(index++, end_pc); --- 986,996 ---- "Illegal exception table range in class file %s", CHECK_(nullHandle)); guarantee_property(handler_pc < code_length, "Illegal exception table handler in class file %s", CHECK_(nullHandle)); if (catch_type_index != 0) { guarantee_property(valid_cp_range(catch_type_index, cp->length()) && ! cp->tag_at(catch_type_index).is_klass_reference(), "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle)); } } exception_handlers->int_at_put(index++, start_pc); exception_handlers->int_at_put(index++, end_pc);
*** 1114,1124 **** if (tag == ITEM_Long || tag == ITEM_Double) { index++; } else if (tag == ITEM_Object) { u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK); guarantee_property(valid_cp_range(class_index, cp->length()) && ! cp->tag_at(class_index).is_unresolved_klass(), "Bad class index %u in StackMap in class file %s", class_index, CHECK); } else if (tag == ITEM_Uninitialized) { u2 offset = u2_array[i2++] = cfs->get_u2(CHECK); guarantee_property( --- 1225,1235 ---- if (tag == ITEM_Long || tag == ITEM_Double) { index++; } else if (tag == ITEM_Object) { u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK); guarantee_property(valid_cp_range(class_index, cp->length()) && ! cp->tag_at(class_index).is_klass_reference(), "Bad class index %u in StackMap in class file %s", class_index, CHECK); } else if (tag == ITEM_Uninitialized) { u2 offset = u2_array[i2++] = cfs->get_u2(CHECK); guarantee_property(
*** 2337,2346 **** --- 2448,2458 ---- instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, Handle class_loader, Handle protection_domain, + GrowableArray<Handle>* cp_patches, symbolHandle& parsed_name, TRAPS) { // So that JVMTI can cache class file in the state before retransformable agents // have modified it unsigned char *cached_class_file_bytes = NULL;
*** 2368,2377 **** --- 2480,2490 ---- cfs = new ClassFileStream(ptr, end_ptr - ptr, cfs->source()); set_stream(cfs); } } + _cp_patches = cp_patches; instanceKlassHandle nullHandle; // Figure out whether we can skip format checking (matching classic VM behavior) _need_verify = Verifier::should_verify_for(class_loader());
*** 2498,2515 **** "Invalid superclass index %u in class file %s", super_class_index, CHECK_(nullHandle)); } else { check_property(valid_cp_range(super_class_index, cp_size) && ! cp->tag_at(super_class_index).is_unresolved_klass(), "Invalid superclass index %u in class file %s", super_class_index, CHECK_(nullHandle)); // The class name should be legal because it is checked when parsing constant pool. // However, make sure it is not an array type. if (_need_verify) { ! guarantee_property(cp->unresolved_klass_at(super_class_index)->byte_at(0) != JVM_SIGNATURE_ARRAY, "Bad superclass name in class file %s", CHECK_(nullHandle)); } } // Interfaces --- 2611,2636 ---- "Invalid superclass index %u in class file %s", super_class_index, CHECK_(nullHandle)); } else { check_property(valid_cp_range(super_class_index, cp_size) && ! cp->tag_at(super_class_index).is_klass_reference(), "Invalid superclass index %u in class file %s", super_class_index, CHECK_(nullHandle)); // The class name should be legal because it is checked when parsing constant pool. // However, make sure it is not an array type. + bool is_array = false; + if (cp->tag_at(super_class_index).is_klass()) { + super_klass = instanceKlassHandle(THREAD, cp->resolved_klass_at(super_class_index)); + if (_need_verify) + is_array = super_klass->oop_is_array(); + } else if (_need_verify) { + is_array = (cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY); + } if (_need_verify) { ! guarantee_property(!is_array, "Bad superclass name in class file %s", CHECK_(nullHandle)); } } // Interfaces
*** 2545,2555 **** objArrayHandle methods_annotations(THREAD, methods_annotations_oop); objArrayHandle methods_parameter_annotations(THREAD, methods_parameter_annotations_oop); objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop); // We check super class after class file is parsed and format is checked ! if (super_class_index > 0) { symbolHandle sk (THREAD, cp->klass_name_at(super_class_index)); if (access_flags.is_interface()) { // Before attempting to resolve the superclass, check for class format // errors not checked yet. guarantee_property(sk() == vmSymbols::java_lang_Object(), --- 2666,2676 ---- objArrayHandle methods_annotations(THREAD, methods_annotations_oop); objArrayHandle methods_parameter_annotations(THREAD, methods_parameter_annotations_oop); objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop); // We check super class after class file is parsed and format is checked ! if (super_class_index > 0 && super_klass.is_null()) { symbolHandle sk (THREAD, cp->klass_name_at(super_class_index)); if (access_flags.is_interface()) { // Before attempting to resolve the superclass, check for class format // errors not checked yet. guarantee_property(sk() == vmSymbols::java_lang_Object(),
*** 2562,2571 **** --- 2683,2695 ---- protection_domain, true, CHECK_(nullHandle)); KlassHandle kh (THREAD, k); super_klass = instanceKlassHandle(THREAD, kh()); + cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve + } + if (super_klass.not_null()) { if (super_klass->is_interface()) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbolHandles::java_lang_IncompatibleClassChangeError(),
*** 2971,2980 **** --- 3095,3105 ---- this_klass->set_has_final_method(); } this_klass->set_method_ordering(method_ordering()); this_klass->set_initial_method_idnum(methods->length()); this_klass->set_name(cp->klass_name_at(this_class_index)); + cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve this_klass->set_protection_domain(protection_domain()); this_klass->set_fields_annotations(fields_annotations()); this_klass->set_methods_annotations(methods_annotations()); this_klass->set_methods_parameter_annotations(methods_parameter_annotations()); this_klass->set_methods_default_annotations(methods_default_annotations());