1 /* 2 * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "cds/cdsConfig.hpp" 26 #include "classfile/symbolTable.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "classfile/systemDictionaryShared.hpp" 29 #include "classfile/verificationType.hpp" 30 #include "classfile/verifier.hpp" 31 #include "classfile/vmClasses.hpp" 32 #include "classfile/vmSymbols.hpp" 33 #include "logging/log.hpp" 34 #include "oops/klass.inline.hpp" 35 #include "runtime/handles.inline.hpp" 36 37 VerificationType VerificationType::from_tag(u1 tag) { 38 switch (tag) { 39 case ITEM_Top: return bogus_type(); 40 case ITEM_Integer: return integer_type(); 41 case ITEM_Float: return float_type(); 42 case ITEM_Double: return double_type(); 43 case ITEM_Long: return long_type(); 44 case ITEM_Null: return null_type(); 45 default: 46 ShouldNotReachHere(); 47 return bogus_type(); 48 } 49 } 50 51 // Potentially resolve the target class and from class, and check whether the from class is assignable 52 // to the target class. The current_klass is the class being verified - it could also be the target in some 53 // cases, and otherwise is needed to obtain the correct classloader for resolving the other classes. 54 bool VerificationType::resolve_and_check_assignability(InstanceKlass* current_klass, Symbol* target_name, Symbol* from_name, 55 bool from_field_is_protected, bool from_is_array, 56 bool from_is_object, bool* target_is_interface, TRAPS) { 57 HandleMark hm(THREAD); 58 Klass* target_klass; 59 if (current_klass->is_hidden() && current_klass->name() == target_name) { 60 target_klass = current_klass; 61 } else { 62 target_klass = SystemDictionary::resolve_or_fail( 63 target_name, Handle(THREAD, current_klass->class_loader()), true, CHECK_false); 64 if (log_is_enabled(Debug, class, resolve)) { 65 Verifier::trace_class_resolution(target_klass, current_klass); 66 } 67 } 68 69 bool is_intf = target_klass->is_interface(); 70 if (target_is_interface != nullptr) { 71 *target_is_interface = is_intf; 72 } 73 74 if (is_intf && (!from_field_is_protected || 75 from_name != vmSymbols::java_lang_Object())) { 76 // If we are not trying to access a protected field or method in 77 // java.lang.Object then, for arrays, we only allow assignability 78 // to interfaces java.lang.Cloneable and java.io.Serializable. 79 // Otherwise, we treat interfaces as java.lang.Object. 80 return !from_is_array || 81 target_klass == vmClasses::Cloneable_klass() || 82 target_klass == vmClasses::Serializable_klass(); 83 } else if (from_is_object) { 84 Klass* from_klass; 85 if (current_klass->is_hidden() && current_klass->name() == from_name) { 86 from_klass = current_klass; 87 } else { 88 from_klass = SystemDictionary::resolve_or_fail( 89 from_name, Handle(THREAD, current_klass->class_loader()), true, CHECK_false); 90 if (log_is_enabled(Debug, class, resolve)) { 91 Verifier::trace_class_resolution(from_klass, current_klass); 92 } 93 } 94 return from_klass->is_subclass_of(target_klass); 95 } 96 97 return false; 98 } 99 100 bool VerificationType::is_reference_assignable_from( 101 const VerificationType& from, ClassVerifier* context, 102 bool from_field_is_protected, bool* this_is_interface, TRAPS) const { 103 104 if (from.is_null()) { 105 // null is assignable to any reference 106 return true; 107 } else if (is_null()) { 108 return false; 109 } else if (name() == from.name()) { 110 return true; 111 } else if (is_object()) { 112 // We need check the class hierarchy to check assignability 113 if (name() == vmSymbols::java_lang_Object()) { 114 // any object or array is assignable to java.lang.Object 115 return true; 116 } 117 118 #if INCLUDE_CDS 119 if (CDSConfig::is_dumping_archive()) { 120 bool skip_assignability_check = false; 121 SystemDictionaryShared::add_verification_constraint(context->current_class(), 122 name(), from.name(), from_field_is_protected, from.is_array(), 123 from.is_object(), &skip_assignability_check); 124 if (skip_assignability_check) { 125 // We are not able to resolve name() or from.name(). The actual assignability check 126 // will be delayed until runtime. 127 return true; 128 } 129 } 130 #endif 131 return resolve_and_check_assignability(context->current_class(), name(), from.name(), 132 from_field_is_protected, from.is_array(), 133 from.is_object(), this_is_interface, THREAD); 134 } else if (is_array() && from.is_array()) { 135 VerificationType comp_this = get_component(context); 136 VerificationType comp_from = from.get_component(context); 137 if (!comp_this.is_bogus() && !comp_from.is_bogus()) { 138 return comp_this.is_component_assignable_from(comp_from, context, 139 from_field_is_protected, THREAD); 140 } 141 } 142 return false; 143 } 144 145 VerificationType VerificationType::get_component(ClassVerifier *context) const { 146 assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array"); 147 SignatureStream ss(name(), false); 148 ss.skip_array_prefix(1); 149 switch (ss.type()) { 150 case T_BOOLEAN: return VerificationType(Boolean); 151 case T_BYTE: return VerificationType(Byte); 152 case T_CHAR: return VerificationType(Char); 153 case T_SHORT: return VerificationType(Short); 154 case T_INT: return VerificationType(Integer); 155 case T_LONG: return VerificationType(Long); 156 case T_FLOAT: return VerificationType(Float); 157 case T_DOUBLE: return VerificationType(Double); 158 case T_ARRAY: 159 case T_OBJECT: { 160 guarantee(ss.is_reference(), "unchecked verifier input?"); 161 Symbol* component = ss.as_symbol(); 162 // Create another symbol to save as signature stream unreferences this symbol. 163 Symbol* component_copy = context->create_temporary_symbol(component); 164 assert(component_copy == component, "symbols don't match"); 165 return VerificationType::reference_type(component_copy); 166 } 167 default: 168 // Met an invalid type signature, e.g. [X 169 return VerificationType::bogus_type(); 170 } 171 } 172 173 void VerificationType::print_on(outputStream* st) const { 174 switch (_u._data) { 175 case Bogus: st->print("top"); break; 176 case Category1: st->print("category1"); break; 177 case Category2: st->print("category2"); break; 178 case Category2_2nd: st->print("category2_2nd"); break; 179 case Boolean: st->print("boolean"); break; 180 case Byte: st->print("byte"); break; 181 case Short: st->print("short"); break; 182 case Char: st->print("char"); break; 183 case Integer: st->print("integer"); break; 184 case Float: st->print("float"); break; 185 case Long: st->print("long"); break; 186 case Double: st->print("double"); break; 187 case Long_2nd: st->print("long_2nd"); break; 188 case Double_2nd: st->print("double_2nd"); break; 189 case Null: st->print("null"); break; 190 case ReferenceQuery: st->print("reference type"); break; 191 case Category1Query: st->print("category1 type"); break; 192 case Category2Query: st->print("category2 type"); break; 193 case Category2_2ndQuery: st->print("category2_2nd type"); break; 194 default: 195 if (is_uninitialized_this()) { 196 st->print("uninitializedThis"); 197 } else if (is_uninitialized()) { 198 st->print("uninitialized %d", bci()); 199 } else { 200 if (name() != nullptr) { 201 name()->print_value_on(st); 202 } else { 203 st->print_cr("null"); 204 } 205 } 206 } 207 }