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.util.Arrays; 28 29 /// From `stackMapFrame.cpp`. 30 class VerificationFrame { 31 32 public static final int FLAG_THIS_UNINIT = 0x01; 33 34 private int _offset; 35 private int _locals_size, _stack_size; 36 private int _stack_mark; 37 private final int _max_locals, _max_stack; 38 private int _flags; 39 private final VerificationType[] _locals, _stack; 40 private final VerifierImpl _verifier; 41 42 public VerificationFrame(int offset, int flags, int locals_size, int stack_size, int max_locals, int max_stack, VerificationType[] locals, VerificationType[] stack, VerifierImpl v) { 43 this._offset = offset; 44 this._locals_size = locals_size; 45 this._stack_size = stack_size; 46 this._stack_mark = -1; 47 this._max_locals = max_locals; 48 this._max_stack = max_stack; 49 this._flags = flags; 50 this._locals = locals; 51 this._stack = stack; 52 this._verifier = v; 53 } 54 55 @Override 56 public String toString() { 57 return "frame @" + _offset + " with locals " + (_locals == null ? "[]" : Arrays.asList(_locals)) + " and stack " + (_stack == null ? "[]" : Arrays.asList(_stack)); 58 } 59 60 void set_offset(int offset) { 61 this._offset = offset; 62 } 63 64 void set_flags(int flags) { 65 _flags = flags; 66 } 67 68 void set_locals_size(int locals_size) { 69 _locals_size = locals_size; 70 } 71 72 void set_stack_size(int stack_size) { 73 _stack_size = _stack_mark = stack_size; 74 } 75 76 int offset() { 77 return _offset; 78 } 79 80 VerifierImpl verifier() { 81 return _verifier; 82 } 83 84 int flags() { 85 return _flags; 86 } 87 88 int locals_size() { 89 return _locals_size; 90 } 91 92 VerificationType[] locals() { 93 return _locals; 94 } 95 96 int stack_size() { 97 return _stack_size; 98 } 99 100 VerificationType[] stack() { 101 return _stack; 102 } 103 104 int max_locals() { 105 return _max_locals; 106 } 107 108 boolean flag_this_uninit() { 109 return (_flags & FLAG_THIS_UNINIT) == FLAG_THIS_UNINIT; 110 } 111 112 void reset() { 113 for (int i = 0; i < _max_locals; i++) { 114 _locals[i] = VerificationType.bogus_type; 115 } 116 for (int i = 0; i < _max_stack; i++) { 117 _stack[i] = VerificationType.bogus_type; 118 } 119 } 120 121 void set_mark() { 122 if (_stack_mark != -1) { 123 for (int i = _stack_mark - 1; i >= _stack_size; --i) { 124 _stack[i] = VerificationType.bogus_type; 125 } 126 _stack_mark = _stack_size; 127 } 128 } 129 130 void push_stack(VerificationType type) { 131 if (type.is_check()) _verifier.verifyError("Must be a real type"); 132 if (_stack_size >= _max_stack) { 133 _verifier.verifyError("Operand stack overflow"); 134 } 135 _stack[_stack_size++] = type; 136 } 137 138 void push_stack_2(VerificationType type1, VerificationType type2) { 139 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double"); 140 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2"); 141 if (_stack_size >= _max_stack - 1) { 142 _verifier.verifyError("Operand stack overflow"); 143 } 144 _stack[_stack_size++] = type1; 145 _stack[_stack_size++] = type2; 146 } 147 148 VerificationType pop_stack() { 149 if (_stack_size <= 0) { 150 _verifier.verifyError("Operand stack underflow"); 151 } 152 return _stack[--_stack_size]; 153 } 154 155 VerificationType pop_stack(VerificationType type) { 156 if (_stack_size != 0) { 157 VerificationType top = _stack[_stack_size - 1]; 158 boolean subtype = type.is_assignable_from(top, verifier()); 159 if (subtype) { 160 --_stack_size; 161 return top; 162 } 163 } 164 return pop_stack_ex(type); 165 } 166 167 void pop_stack_2(VerificationType type1, VerificationType type2) { 168 if (!(type1.is_long2() || type1.is_double2())) _verifier.verifyError("must be long/double"); 169 if (!(type2.is_long() || type2.is_double())) _verifier.verifyError("must be long/double_2"); 170 if (_stack_size >= 2) { 171 VerificationType top1 = _stack[_stack_size - 1]; 172 boolean subtype1 = type1.is_assignable_from(top1, verifier()); 173 VerificationType top2 = _stack[_stack_size - 2]; 174 boolean subtype2 = type2.is_assignable_from(top2, verifier()); 175 if (subtype1 && subtype2) { 176 _stack_size -= 2; 177 return; 178 } 179 } 180 pop_stack_ex(type1); 181 pop_stack_ex(type2); 182 } 183 184 VerificationFrame(int max_locals, int max_stack, VerifierImpl verifier) { 185 _offset = 0; 186 _locals_size = 0; 187 _stack_size = 0; 188 _stack_mark = 0; 189 _max_locals = max_locals; 190 _max_stack = max_stack; 191 _flags = 0; 192 _verifier = verifier; 193 _locals = new VerificationType[max_locals]; 194 _stack = new VerificationType[max_stack]; 195 for (int i = 0; i < max_locals; i++) { 196 _locals[i] = VerificationType.bogus_type; 197 } 198 for (int i = 0; i < max_stack; i++) { 199 _stack[i] = VerificationType.bogus_type; 200 } 201 } 202 203 VerificationFrame frame_in_exception_handler(int flags) { 204 return new VerificationFrame(_offset, flags, _locals_size, 0, 205 _max_locals, _max_stack, _locals, new VerificationType[1], 206 _verifier); 207 } 208 209 void initialize_object(VerificationType old_object, VerificationType new_object) { 210 int i; 211 for (i = 0; i < _max_locals; i++) { 212 if (_locals[i].equals(old_object)) { 213 _locals[i] = new_object; 214 } 215 } 216 for (i = 0; i < _stack_size; i++) { 217 if (_stack[i].equals(old_object)) { 218 _stack[i] = new_object; 219 } 220 } 221 if (old_object.is_uninitialized_this(_verifier)) { 222 _flags = 0; 223 } 224 } 225 226 VerificationType set_locals_from_arg(VerificationWrapper.MethodWrapper m, VerificationType thisKlass) { 227 var ss = new VerificationSignature(m.descriptor(), true, _verifier); 228 int init_local_num = 0; 229 if (!m.isStatic()) { 230 init_local_num++; 231 if (VerifierImpl.object_initializer_name.equals(m.name()) && !VerifierImpl.java_lang_Object.equals(thisKlass.name())) { 232 _locals[0] = VerificationType.uninitialized_this_type; 233 _flags |= FLAG_THIS_UNINIT; 234 } else { 235 _locals[0] = thisKlass; 236 } 237 } 238 while (!ss.atReturnType()) { 239 init_local_num += _verifier.change_sig_to_verificationType(ss, _locals, init_local_num); 240 ss.next(); 241 } 242 _locals_size = init_local_num; 243 switch (ss.type()) { 244 case T_OBJECT: 245 case T_ARRAY: 246 { 247 String sig = ss.asSymbol(); 248 return VerificationType.reference_type(sig); 249 } 250 case T_INT: return VerificationType.integer_type; 251 case T_BYTE: return VerificationType.byte_type; 252 case T_CHAR: return VerificationType.char_type; 253 case T_SHORT: return VerificationType.short_type; 254 case T_BOOLEAN: return VerificationType.boolean_type; 255 case T_FLOAT: return VerificationType.float_type; 256 case T_DOUBLE: return VerificationType.double_type; 257 case T_LONG: return VerificationType.long_type; 258 case T_VOID: return VerificationType.bogus_type; 259 default: 260 _verifier.verifyError("Should not reach here"); 261 return VerificationType.bogus_type; 262 } 263 } 264 265 void copy_locals(VerificationFrame src) { 266 int len = src.locals_size() < _locals_size ? src.locals_size() : _locals_size; 267 if (len > 0) System.arraycopy(src.locals(), 0, _locals, 0, len); 268 } 269 270 void copy_stack(VerificationFrame src) { 271 int len = src.stack_size() < _stack_size ? src.stack_size() : _stack_size; 272 if (len > 0) System.arraycopy(src.stack(), 0, _stack, 0, len); 273 } 274 275 private int is_assignable_to(VerificationType[] from, VerificationType[] to, int len) { 276 int i = 0; 277 for (; i < len; i++) { 278 if (!to[i].is_assignable_from(from[i], verifier())) { 279 break; 280 } 281 } 282 return i; 283 } 284 285 boolean is_assignable_to(VerificationFrame target) { 286 if (_max_locals != target.max_locals()) { 287 _verifier.verifyError("Locals size mismatch", this, target); 288 } 289 if (_stack_size != target.stack_size()) { 290 _verifier.verifyError("Stack size mismatch", this, target); 291 } 292 int mismatch_loc; 293 mismatch_loc = is_assignable_to(_locals, target.locals(), target.locals_size()); 294 if (mismatch_loc != target.locals_size()) { 295 _verifier.verifyError("Bad type", this, target); 296 } 297 mismatch_loc = is_assignable_to(_stack, target.stack(), _stack_size); 298 if (mismatch_loc != _stack_size) { 299 _verifier.verifyError("Bad type", this, target); 300 } 301 302 if ((_flags | target.flags()) == target.flags()) { 303 return true; 304 } else { 305 _verifier.verifyError("Bad flags", this, target); 306 } 307 return false; 308 } 309 310 VerificationType pop_stack_ex(VerificationType type) { 311 if (_stack_size <= 0) { 312 _verifier.verifyError("Operand stack underflow"); 313 } 314 VerificationType top = _stack[--_stack_size]; 315 boolean subtype = type.is_assignable_from(top, verifier()); 316 if (!subtype) { 317 _verifier.verifyError("Bad type on operand stack"); 318 } 319 return top; 320 } 321 322 VerificationType get_local(int index, VerificationType type) { 323 if (index >= _max_locals) { 324 _verifier.verifyError("Local variable table overflow"); 325 } 326 boolean subtype = type.is_assignable_from(_locals[index], 327 verifier()); 328 if (!subtype) { 329 _verifier.verifyError("Bad local variable type"); 330 } 331 if(index >= _locals_size) { _locals_size = index + 1; } 332 return _locals[index]; 333 } 334 335 void get_local_2(int index, VerificationType type1, VerificationType type2) { 336 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double"); 337 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2"); 338 if (index >= _locals_size - 1) { 339 _verifier.verifyError("get long/double overflows locals"); 340 } 341 boolean subtype = type1.is_assignable_from(_locals[index], verifier()); 342 if (!subtype) { 343 _verifier.verifyError("Bad local variable type"); 344 } else { 345 subtype = type2.is_assignable_from(_locals[index + 1], verifier()); 346 if (!subtype) { 347 _verifier.verifyError("Bad local variable type"); 348 } 349 } 350 } 351 352 void set_local(int index, VerificationType type) { 353 if (type.is_check()) _verifier.verifyError("Must be a real type"); 354 if (index >= _max_locals) { 355 _verifier.verifyError("Local variable table overflow"); 356 } 357 if (_locals[index].is_double() || _locals[index].is_long()) { 358 if ((index + 1) >= _locals_size) _verifier.verifyError("Local variable table overflow"); 359 _locals[index + 1] = VerificationType.bogus_type; 360 } 361 if (_locals[index].is_double2() || _locals[index].is_long2()) { 362 if (index < 1) _verifier.verifyError("Local variable table underflow"); 363 _locals[index - 1] = VerificationType.bogus_type; 364 } 365 _locals[index] = type; 366 if (index >= _locals_size) { 367 for (int i=_locals_size; i<index; i++) { 368 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type"); 369 } 370 _locals_size = index + 1; 371 } 372 } 373 374 void set_local_2(int index, VerificationType type1, VerificationType type2) { 375 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double"); 376 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2"); 377 if (index >= _max_locals - 1) { 378 _verifier.verifyError("Local variable table overflow"); 379 } 380 if (_locals[index+1].is_double() || _locals[index+1].is_long()) { 381 if ((index + 2) >= _locals_size) _verifier.verifyError("Local variable table overflow"); 382 _locals[index + 2] = VerificationType.bogus_type; 383 } 384 if (_locals[index].is_double2() || _locals[index].is_long2()) { 385 if (index < 1) _verifier.verifyError("Local variable table underflow"); 386 _locals[index - 1] = VerificationType.bogus_type; 387 } 388 _locals[index] = type1; 389 _locals[index+1] = type2; 390 if (index >= _locals_size - 1) { 391 for (int i=_locals_size; i<index; i++) { 392 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type"); 393 } 394 _locals_size = index + 2; 395 } 396 } 397 }