1 /* 2 * Copyright (c) 2022, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.internal.classfile.impl.verifier; 26 27 import java.lang.classfile.constantpool.NameAndTypeEntry; 28 import java.lang.classfile.constantpool.Utf8Entry; 29 import java.util.Arrays; 30 import java.util.Set; 31 32 import jdk.internal.classfile.impl.TemporaryConstantPool; 33 34 /// From `stackMapFrame.cpp`. 35 class VerificationFrame { 36 37 public static final int FLAG_THIS_UNINIT = 0x01; 38 39 private int _offset; 40 private int _locals_size, _stack_size; 41 private int _stack_mark; 42 private final int _max_locals, _max_stack; 43 private int _flags; 44 private final VerificationType[] _locals, _stack; 45 private Set<NameAndTypeEntry> _assert_unset_fields; 46 private final VerifierImpl _verifier; 47 48 public VerificationFrame(int offset, int flags, int locals_size, int stack_size, int max_locals, int max_stack, 49 VerificationType[] locals, VerificationType[] stack, Set<NameAndTypeEntry> assert_unset_fields, VerifierImpl v) { 50 this._offset = offset; 51 this._locals_size = locals_size; 52 this._stack_size = stack_size; 53 this._stack_mark = -1; 54 this._max_locals = max_locals; 55 this._max_stack = max_stack; 56 this._flags = flags; 57 this._locals = locals; 58 this._stack = stack; 59 this._assert_unset_fields = assert_unset_fields; 60 this._verifier = v; 61 } 62 63 @Override 64 public String toString() { 65 return "frame @" + _offset + " with locals " + (_locals == null ? "[]" : Arrays.asList(_locals)) + " and stack " + (_stack == null ? "[]" : Arrays.asList(_stack)); 66 } 67 68 void set_offset(int offset) { 69 this._offset = offset; 70 } 71 72 void set_flags(int flags) { 73 _flags = flags; 74 } 75 76 void set_locals_size(int locals_size) { 77 _locals_size = locals_size; 78 } 79 80 void set_stack_size(int stack_size) { 81 _stack_size = _stack_mark = stack_size; 82 } 83 84 int offset() { 85 return _offset; 86 } 87 88 VerifierImpl verifier() { 89 return _verifier; 90 } 91 92 int flags() { 93 return _flags; 94 } 95 96 int locals_size() { 97 return _locals_size; 98 } 99 100 VerificationType[] locals() { 101 return _locals; 102 } 103 104 int stack_size() { 105 return _stack_size; 106 } 107 108 VerificationType[] stack() { 109 return _stack; 110 } 111 112 int max_locals() { 113 return _max_locals; 114 } 115 116 boolean flag_this_uninit() { 117 return (_flags & FLAG_THIS_UNINIT) == FLAG_THIS_UNINIT; 118 } 119 120 Set<NameAndTypeEntry> assert_unset_fields() { 121 return _assert_unset_fields; 122 } 123 124 void set_assert_unset_fields(Set<NameAndTypeEntry> table) { 125 _assert_unset_fields = table; 126 } 127 128 // Called when verifying putfields to mark strict instance fields as satisfied 129 boolean satisfy_unset_field(Utf8Entry name, Utf8Entry signature) { 130 var nat = TemporaryConstantPool.INSTANCE.nameAndTypeEntry(name, signature); 131 return _assert_unset_fields.remove(nat); 132 } 133 134 // Verify that all strict fields have been initialized 135 // Strict fields must be initialized before the super constructor is called 136 boolean verify_unset_fields_satisfied() { 137 return _assert_unset_fields.isEmpty(); 138 } 139 140 // Merge incoming unset strict fields from StackMapTable with 141 // initial strict instance fields 142 Set<NameAndTypeEntry> merge_unset_fields(Set<NameAndTypeEntry> new_fields) { 143 // ClassFile API: We track all strict fields in another structure, noop here 144 return new_fields; 145 } 146 147 boolean verify_unset_fields_compatibility(Set<NameAndTypeEntry> target_table) { 148 for (var e : _assert_unset_fields) { 149 if (!target_table.contains(e)) 150 return false; 151 } 152 return true; 153 } 154 155 void unsatisfied_strict_fields_error(VerificationWrapper klass, int bci) { 156 _verifier.verifyError("All strict final fields must be initialized before super(): %d field(s), %s" 157 .formatted(_assert_unset_fields.size(), _assert_unset_fields)); 158 } 159 160 void print_strict_fields(Set<NameAndTypeEntry> table) { 161 // ignore, we don't do stdout/err 162 } 163 164 void reset() { 165 for (int i = 0; i < _max_locals; i++) { 166 _locals[i] = VerificationType.bogus_type; 167 } 168 for (int i = 0; i < _max_stack; i++) { 169 _stack[i] = VerificationType.bogus_type; 170 } 171 } 172 173 void set_mark() { 174 if (_stack_mark != -1) { 175 for (int i = _stack_mark - 1; i >= _stack_size; --i) { 176 _stack[i] = VerificationType.bogus_type; 177 } 178 _stack_mark = _stack_size; 179 } 180 } 181 182 void push_stack(VerificationType type) { 183 if (type.is_check()) _verifier.verifyError("Must be a real type"); 184 if (_stack_size >= _max_stack) { 185 _verifier.verifyError("Operand stack overflow"); 186 } 187 _stack[_stack_size++] = type; 188 } 189 190 void push_stack_2(VerificationType type1, VerificationType type2) { 191 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double"); 192 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2"); 193 if (_stack_size >= _max_stack - 1) { 194 _verifier.verifyError("Operand stack overflow"); 195 } 196 _stack[_stack_size++] = type1; 197 _stack[_stack_size++] = type2; 198 } 199 200 VerificationType pop_stack() { 201 if (_stack_size <= 0) { 202 _verifier.verifyError("Operand stack underflow"); 203 } 204 return _stack[--_stack_size]; 205 } 206 207 VerificationType pop_stack(VerificationType type) { 208 if (_stack_size != 0) { 209 VerificationType top = _stack[_stack_size - 1]; 210 boolean subtype = type.is_assignable_from(top, verifier()); 211 if (subtype) { 212 --_stack_size; 213 return top; 214 } 215 } 216 return pop_stack_ex(type); 217 } 218 219 void pop_stack_2(VerificationType type1, VerificationType type2) { 220 if (!(type1.is_long2() || type1.is_double2())) _verifier.verifyError("must be long/double"); 221 if (!(type2.is_long() || type2.is_double())) _verifier.verifyError("must be long/double_2"); 222 if (_stack_size >= 2) { 223 VerificationType top1 = _stack[_stack_size - 1]; 224 boolean subtype1 = type1.is_assignable_from(top1, verifier()); 225 VerificationType top2 = _stack[_stack_size - 2]; 226 boolean subtype2 = type2.is_assignable_from(top2, verifier()); 227 if (subtype1 && subtype2) { 228 _stack_size -= 2; 229 return; 230 } 231 } 232 pop_stack_ex(type1); 233 pop_stack_ex(type2); 234 } 235 236 VerificationFrame(int max_locals, int max_stack, Set<NameAndTypeEntry> initial_strict_fields, VerifierImpl verifier) { 237 _offset = 0; 238 _locals_size = 0; 239 _stack_size = 0; 240 _stack_mark = 0; 241 _max_locals = max_locals; 242 _max_stack = max_stack; 243 _flags = 0; 244 _verifier = verifier; 245 _locals = new VerificationType[max_locals]; 246 _stack = new VerificationType[max_stack]; 247 for (int i = 0; i < max_locals; i++) { 248 _locals[i] = VerificationType.bogus_type; 249 } 250 for (int i = 0; i < max_stack; i++) { 251 _stack[i] = VerificationType.bogus_type; 252 } 253 _assert_unset_fields = initial_strict_fields; 254 } 255 256 VerificationFrame frame_in_exception_handler(int flags) { 257 return new VerificationFrame(_offset, flags, _locals_size, 0, 258 _max_locals, _max_stack, _locals, new VerificationType[1], 259 _assert_unset_fields, _verifier); 260 } 261 262 void initialize_object(VerificationType old_object, VerificationType new_object) { 263 int i; 264 for (i = 0; i < _max_locals; i++) { 265 if (_locals[i].equals(old_object)) { 266 _locals[i] = new_object; 267 } 268 } 269 for (i = 0; i < _stack_size; i++) { 270 if (_stack[i].equals(old_object)) { 271 _stack[i] = new_object; 272 } 273 } 274 if (old_object.is_uninitialized_this(_verifier)) { 275 _flags = 0; 276 } 277 } 278 279 VerificationType set_locals_from_arg(VerificationWrapper.MethodWrapper m, VerificationType thisKlass) { 280 var ss = new VerificationSignature(m.descriptor(), true, _verifier); 281 int init_local_num = 0; 282 if (!m.isStatic()) { 283 init_local_num++; 284 if (VerifierImpl.object_initializer_name.equals(m.name()) && !VerifierImpl.java_lang_Object.equals(thisKlass.name())) { 285 _locals[0] = VerificationType.uninitialized_this_type; 286 _flags |= FLAG_THIS_UNINIT; 287 } else { 288 _locals[0] = thisKlass; 289 } 290 } 291 while (!ss.atReturnType()) { 292 init_local_num += _verifier.change_sig_to_verificationType(ss, _locals, init_local_num); 293 ss.next(); 294 } 295 _locals_size = init_local_num; 296 switch (ss.type()) { 297 case T_OBJECT: 298 case T_ARRAY: 299 { 300 String sig = ss.asSymbol(); 301 return VerificationType.reference_type(sig); 302 } 303 case T_INT: return VerificationType.integer_type; 304 case T_BYTE: return VerificationType.byte_type; 305 case T_CHAR: return VerificationType.char_type; 306 case T_SHORT: return VerificationType.short_type; 307 case T_BOOLEAN: return VerificationType.boolean_type; 308 case T_FLOAT: return VerificationType.float_type; 309 case T_DOUBLE: return VerificationType.double_type; 310 case T_LONG: return VerificationType.long_type; 311 case T_VOID: return VerificationType.bogus_type; 312 default: 313 _verifier.verifyError("Should not reach here"); 314 return VerificationType.bogus_type; 315 } 316 } 317 318 void copy_locals(VerificationFrame src) { 319 int len = src.locals_size() < _locals_size ? src.locals_size() : _locals_size; 320 if (len > 0) System.arraycopy(src.locals(), 0, _locals, 0, len); 321 } 322 323 void copy_stack(VerificationFrame src) { 324 int len = src.stack_size() < _stack_size ? src.stack_size() : _stack_size; 325 if (len > 0) System.arraycopy(src.stack(), 0, _stack, 0, len); 326 } 327 328 private int is_assignable_to(VerificationType[] from, VerificationType[] to, int len) { 329 int i = 0; 330 for (; i < len; i++) { 331 if (!to[i].is_assignable_from(from[i], verifier())) { 332 break; 333 } 334 } 335 return i; 336 } 337 338 boolean is_assignable_to(VerificationFrame target) { 339 if (_max_locals != target.max_locals()) { 340 _verifier.verifyError("Locals size mismatch", this, target); 341 } 342 if (_stack_size != target.stack_size()) { 343 _verifier.verifyError("Stack size mismatch", this, target); 344 } 345 int mismatch_loc; 346 mismatch_loc = is_assignable_to(_locals, target.locals(), target.locals_size()); 347 if (mismatch_loc != target.locals_size()) { 348 _verifier.verifyError("Bad type", this, target); 349 } 350 mismatch_loc = is_assignable_to(_stack, target.stack(), _stack_size); 351 if (mismatch_loc != _stack_size) { 352 _verifier.verifyError("Bad type", this, target); 353 } 354 355 // Check that assert unset fields are compatible 356 boolean compatible = verify_unset_fields_compatibility(target.assert_unset_fields()); 357 if (!compatible) { 358 print_strict_fields(assert_unset_fields()); 359 print_strict_fields(target.assert_unset_fields()); 360 _verifier.verifyError("Strict fields mismatch from %s to %s".formatted( 361 assert_unset_fields(), target.assert_unset_fields()), this, target); 362 return false; 363 } 364 365 if ((_flags | target.flags()) == target.flags()) { 366 return true; 367 } else { 368 _verifier.verifyError("Bad flags", this, target); 369 } 370 return false; 371 } 372 373 VerificationType pop_stack_ex(VerificationType type) { 374 if (_stack_size <= 0) { 375 _verifier.verifyError("Operand stack underflow"); 376 } 377 VerificationType top = _stack[--_stack_size]; 378 boolean subtype = type.is_assignable_from(top, verifier()); 379 if (!subtype) { 380 _verifier.verifyError("Bad type on operand stack"); 381 } 382 return top; 383 } 384 385 VerificationType get_local(int index, VerificationType type) { 386 if (index >= _max_locals) { 387 _verifier.verifyError("Local variable table overflow"); 388 } 389 boolean subtype = type.is_assignable_from(_locals[index], 390 verifier()); 391 if (!subtype) { 392 _verifier.verifyError("Bad local variable type"); 393 } 394 if(index >= _locals_size) { _locals_size = index + 1; } 395 return _locals[index]; 396 } 397 398 void get_local_2(int index, VerificationType type1, VerificationType type2) { 399 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double"); 400 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2"); 401 if (index >= _locals_size - 1) { 402 _verifier.verifyError("get long/double overflows locals"); 403 } 404 boolean subtype = type1.is_assignable_from(_locals[index], verifier()); 405 if (!subtype) { 406 _verifier.verifyError("Bad local variable type"); 407 } else { 408 subtype = type2.is_assignable_from(_locals[index + 1], verifier()); 409 if (!subtype) { 410 _verifier.verifyError("Bad local variable type"); 411 } 412 } 413 } 414 415 void set_local(int index, VerificationType type) { 416 if (type.is_check()) _verifier.verifyError("Must be a real type"); 417 if (index >= _max_locals) { 418 _verifier.verifyError("Local variable table overflow"); 419 } 420 if (_locals[index].is_double() || _locals[index].is_long()) { 421 if ((index + 1) >= _locals_size) _verifier.verifyError("Local variable table overflow"); 422 _locals[index + 1] = VerificationType.bogus_type; 423 } 424 if (_locals[index].is_double2() || _locals[index].is_long2()) { 425 if (index < 1) _verifier.verifyError("Local variable table underflow"); 426 _locals[index - 1] = VerificationType.bogus_type; 427 } 428 _locals[index] = type; 429 if (index >= _locals_size) { 430 for (int i=_locals_size; i<index; i++) { 431 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type"); 432 } 433 _locals_size = index + 1; 434 } 435 } 436 437 void set_local_2(int index, VerificationType type1, VerificationType type2) { 438 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double"); 439 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2"); 440 if (index >= _max_locals - 1) { 441 _verifier.verifyError("Local variable table overflow"); 442 } 443 if (_locals[index+1].is_double() || _locals[index+1].is_long()) { 444 if ((index + 2) >= _locals_size) _verifier.verifyError("Local variable table overflow"); 445 _locals[index + 2] = VerificationType.bogus_type; 446 } 447 if (_locals[index].is_double2() || _locals[index].is_long2()) { 448 if (index < 1) _verifier.verifyError("Local variable table underflow"); 449 _locals[index - 1] = VerificationType.bogus_type; 450 } 451 _locals[index] = type1; 452 _locals[index+1] = type2; 453 if (index >= _locals_size - 1) { 454 for (int i=_locals_size; i<index; i++) { 455 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type"); 456 } 457 _locals_size = index + 2; 458 } 459 } 460 }