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 "classfile/stackMapTable.hpp" 26 #include "classfile/verifier.hpp" 27 #include "memory/resourceArea.hpp" 28 #include "oops/constantPool.hpp" 29 #include "oops/oop.inline.hpp" 30 #include "runtime/handles.inline.hpp" 31 32 StackMapTable::StackMapTable(StackMapReader* reader, TRAPS) { 33 _code_length = reader->code_length(); 34 _frame_count = reader->get_frame_count(); 35 if (_frame_count > 0) { 36 _frame_array = new GrowableArray<StackMapFrame*>(_frame_count); 37 while (!reader->at_end()) { 38 StackMapFrame* frame = reader->next(CHECK_VERIFY(reader->prev_frame()->verifier())); 39 if (frame != nullptr) { 40 _frame_array->push(frame); 41 } 42 } 43 reader->check_end(CHECK); 44 // Correct frame count based on how many actual frames are generated 45 _frame_count = _frame_array->length(); 46 } 47 } 48 49 void StackMapReader::check_offset(StackMapFrame* frame) { 50 int offset = frame->offset(); 51 if (offset >= _code_length || _code_data[offset] == 0) { 52 _verifier->verify_error(ErrorContext::bad_stackmap(0, frame), 53 "StackMapTable error: bad offset"); 54 } 55 } 56 57 void StackMapReader::check_size(TRAPS) { 58 if (_frame_count < _parsed_frame_count) { 59 StackMapStream::stackmap_format_error("wrong attribute size", THREAD); 60 } 61 } 62 63 void StackMapReader::check_end(TRAPS) { 64 assert(_stream->at_end(), "must be"); 65 if (_frame_count != _parsed_frame_count) { 66 StackMapStream::stackmap_format_error("wrong attribute size", THREAD); 67 } 68 } 69 70 // This method is only called by method in StackMapTable. 71 int StackMapTable::get_index_from_offset(int32_t offset) const { 72 int i = 0; 73 for (; i < _frame_count; i++) { 74 if (_frame_array->at(i)->offset() == offset) { 75 return i; 76 } 77 } 78 return i; // frame with offset doesn't exist in the array 79 } 80 81 bool StackMapTable::match_stackmap( 82 StackMapFrame* frame, int32_t target, 83 bool match, bool update, ErrorContext* ctx, TRAPS) const { 84 int index = get_index_from_offset(target); 85 return match_stackmap(frame, target, index, match, update, ctx, THREAD); 86 } 87 88 // Match and/or update current_frame to the frame in stackmap table with 89 // specified offset and frame index. Return true if the two frames match. 90 // 91 // The values of match and update are: _match__update 92 // 93 // checking a branch target: true false 94 // checking an exception handler: true false 95 // linear bytecode verification following an 96 // unconditional branch: false true 97 // linear bytecode verification not following an 98 // unconditional branch: true true 99 bool StackMapTable::match_stackmap( 100 StackMapFrame* frame, int32_t target, int32_t frame_index, 101 bool match, bool update, ErrorContext* ctx, TRAPS) const { 102 if (frame_index < 0 || frame_index >= _frame_count) { 103 *ctx = ErrorContext::missing_stackmap(frame->offset()); 104 frame->verifier()->verify_error( 105 *ctx, "Expecting a stackmap frame at branch target %d", target); 106 return false; 107 } 108 109 StackMapFrame* stackmap_frame = _frame_array->at(frame_index); 110 bool result = true; 111 if (match) { 112 // Has direct control flow from last instruction, need to match the two 113 // frames. 114 result = frame->is_assignable_to(stackmap_frame, 115 ctx, CHECK_VERIFY_(frame->verifier(), result)); 116 } 117 if (update) { 118 // Use the frame in stackmap table as current frame 119 int lsize = stackmap_frame->locals_size(); 120 int ssize = stackmap_frame->stack_size(); 121 if (frame->locals_size() > lsize || frame->stack_size() > ssize) { 122 // Make sure unused type array items are all _bogus_type. 123 frame->reset(); 124 } 125 frame->set_locals_size(lsize); 126 frame->copy_locals(stackmap_frame); 127 frame->set_stack_size(ssize); 128 frame->copy_stack(stackmap_frame); 129 frame->set_flags(stackmap_frame->flags()); 130 frame->set_assert_unset_fields(stackmap_frame->assert_unset_fields()); 131 } 132 return result; 133 } 134 135 void StackMapTable::check_jump_target( 136 StackMapFrame* frame, int32_t target, TRAPS) const { 137 ErrorContext ctx; 138 bool match = match_stackmap( 139 frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); 140 if (!match || (target < 0 || target >= _code_length)) { 141 frame->verifier()->verify_error(ctx, 142 "Inconsistent stackmap frames at branch target %d", target); 143 } 144 } 145 146 void StackMapTable::print_on(outputStream* str) const { 147 str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count); 148 str->indent().print_cr("table = { "); 149 { 150 streamIndentor si(str); 151 for (int32_t i = 0; i < _frame_count; ++i) { 152 _frame_array->at(i)->print_on(str); 153 } 154 } 155 str->print_cr(" }"); 156 } 157 158 StackMapReader::StackMapReader(ClassVerifier* v, StackMapStream* stream, 159 char* code_data, int32_t code_len, 160 StackMapFrame* init_frame, 161 u2 max_locals, u2 max_stack, 162 StackMapFrame::AssertUnsetFieldTable* initial_strict_fields, TRAPS) : 163 _verifier(v), _stream(stream), _code_data(code_data), 164 _code_length(code_len), _parsed_frame_count(0), 165 _prev_frame(init_frame), _max_locals(max_locals), 166 _max_stack(max_stack), _assert_unset_fields_buffer(initial_strict_fields), 167 _first(true) { 168 methodHandle m = v->method(); 169 if (m->has_stackmap_table()) { 170 _cp = constantPoolHandle(THREAD, m->constants()); 171 _frame_count = _stream->get_u2(CHECK); 172 } else { 173 // There's no stackmap table present. Frame count and size are 0. 174 _frame_count = 0; 175 } 176 } 177 178 int32_t StackMapReader::chop( 179 VerificationType* locals, int32_t length, int32_t chops) { 180 if (locals == nullptr) return -1; 181 int32_t pos = length - 1; 182 for (int32_t i=0; i<chops; i++) { 183 if (locals[pos].is_category2_2nd()) { 184 pos -= 2; 185 } else { 186 pos --; 187 } 188 if (pos<0 && i<(chops-1)) return -1; 189 } 190 return pos+1; 191 } 192 193 #define CHECK_NT CHECK_(VerificationType::bogus_type()) 194 195 VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) { 196 u1 tag = _stream->get_u1(CHECK_NT); 197 if (tag < (u1)ITEM_UninitializedThis) { 198 return VerificationType::from_tag(tag); 199 } 200 if (tag == ITEM_Object) { 201 u2 class_index = _stream->get_u2(CHECK_NT); 202 int nconstants = _cp->length(); 203 if ((class_index <= 0 || class_index >= nconstants) || 204 (!_cp->tag_at(class_index).is_klass() && 205 !_cp->tag_at(class_index).is_unresolved_klass())) { 206 _stream->stackmap_format_error("bad class index", THREAD); 207 return VerificationType::bogus_type(); 208 } 209 Symbol* klass_name = _cp->klass_name_at(class_index); 210 return VerificationType::reference_type(klass_name); 211 } 212 if (tag == ITEM_UninitializedThis) { 213 if (flags != nullptr) { 214 *flags |= FLAG_THIS_UNINIT; 215 } 216 return VerificationType::uninitialized_this_type(); 217 } 218 if (tag == ITEM_Uninitialized) { 219 u2 offset = _stream->get_u2(CHECK_NT); 220 if (offset >= _code_length || 221 _code_data[offset] != ClassVerifier::NEW_OFFSET) { 222 _verifier->class_format_error( 223 "StackMapTable format error: bad offset for Uninitialized"); 224 return VerificationType::bogus_type(); 225 } 226 return VerificationType::uninitialized_type(offset); 227 } 228 _stream->stackmap_format_error("bad verification type", THREAD); 229 return VerificationType::bogus_type(); 230 } 231 232 StackMapFrame* StackMapReader::next(TRAPS) { 233 _parsed_frame_count++; 234 check_size(CHECK_NULL); 235 StackMapFrame* frame = next_helper(CHECK_VERIFY_(_verifier, nullptr)); 236 if (frame != nullptr) { 237 check_offset(frame); 238 if (frame->verifier()->has_error()) { 239 return nullptr; 240 } 241 _prev_frame = frame; 242 } 243 return frame; 244 } 245 246 StackMapFrame* StackMapReader::next_helper(TRAPS) { 247 StackMapFrame* frame; 248 int offset; 249 VerificationType* locals = nullptr; 250 u1 frame_type = _stream->get_u1(CHECK_NULL); 251 if (frame_type == EARLY_LARVAL) { 252 u2 num_unset_fields = _stream->get_u2(CHECK_NULL); 253 StackMapFrame::AssertUnsetFieldTable* new_fields = new StackMapFrame::AssertUnsetFieldTable(); 254 255 for (u2 i = 0; i < num_unset_fields; i++) { 256 u2 index = _stream->get_u2(CHECK_NULL); 257 258 if (!_cp->is_within_bounds(index) || !_cp->tag_at(index).is_name_and_type()) { 259 _prev_frame->verifier()->verify_error( 260 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 261 "Invalid constant pool index in early larval frame: %d", index); 262 return nullptr; 263 } 264 265 Symbol* name = _cp->symbol_at(_cp->name_ref_index_at(index)); 266 Symbol* sig = _cp->symbol_at(_cp->signature_ref_index_at(index)); 267 NameAndSig tmp(name, sig); 268 269 if (!_prev_frame->assert_unset_fields()->contains(tmp)) { 270 log_info(verification)("NameAndType %s%s(CP index: %d) is not found among initial strict instance fields", name->as_C_string(), sig->as_C_string(), index); 271 StackMapFrame::print_strict_fields(_prev_frame->assert_unset_fields()); 272 _prev_frame->verifier()->verify_error( 273 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 274 "Strict fields not a subset of initial strict instance fields: %s:%s", name->as_C_string(), sig->as_C_string()); 275 return nullptr; 276 } else { 277 new_fields->put(tmp, false); 278 } 279 } 280 281 // Only modify strict instance fields the frame has uninitialized this 282 if (_prev_frame->flag_this_uninit()) { 283 _assert_unset_fields_buffer = _prev_frame->merge_unset_fields(new_fields); 284 } else if (new_fields->number_of_entries() > 0) { 285 _prev_frame->verifier()->verify_error( 286 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 287 "Cannot have uninitialized strict fields after class initialization"); 288 return nullptr; 289 } 290 291 // Continue reading frame data 292 if (at_end()) { 293 _prev_frame->verifier()->verify_error( 294 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 295 "Early larval frame must be followed by a base frame"); 296 return nullptr; 297 } 298 299 frame_type = _stream->get_u1(CHECK_NULL); 300 if (frame_type == EARLY_LARVAL) { 301 _prev_frame->verifier()->verify_error( 302 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 303 "Early larval frame must be followed by a base frame"); 304 return nullptr; 305 } 306 } 307 308 if (frame_type < 64) { 309 // same_frame 310 if (_first) { 311 offset = frame_type; 312 // Can't share the locals array since that is updated by the verifier. 313 if (_prev_frame->locals_size() > 0) { 314 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 315 THREAD, VerificationType, _prev_frame->locals_size()); 316 } 317 } else { 318 offset = _prev_frame->offset() + frame_type + 1; 319 locals = _prev_frame->locals(); 320 } 321 frame = new StackMapFrame( 322 offset, _prev_frame->flags(), _prev_frame->locals_size(), 0, 323 _max_locals, _max_stack, locals, nullptr, 324 _assert_unset_fields_buffer, _verifier); 325 if (_first && locals != nullptr) { 326 frame->copy_locals(_prev_frame); 327 } 328 _first = false; 329 return frame; 330 } 331 if (frame_type < 128) { 332 // same_locals_1_stack_item_frame 333 if (_first) { 334 offset = frame_type - 64; 335 // Can't share the locals array since that is updated by the verifier. 336 if (_prev_frame->locals_size() > 0) { 337 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 338 THREAD, VerificationType, _prev_frame->locals_size()); 339 } 340 } else { 341 offset = _prev_frame->offset() + frame_type - 63; 342 locals = _prev_frame->locals(); 343 } 344 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 345 THREAD, VerificationType, 2); 346 u2 stack_size = 1; 347 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 348 if (stack[0].is_category2()) { 349 stack[1] = stack[0].to_category2_2nd(); 350 stack_size = 2; 351 } 352 check_verification_type_array_size( 353 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 354 frame = new StackMapFrame( 355 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 356 _max_locals, _max_stack, locals, stack, 357 _assert_unset_fields_buffer, _verifier); 358 if (_first && locals != nullptr) { 359 frame->copy_locals(_prev_frame); 360 } 361 _first = false; 362 return frame; 363 } 364 365 u2 offset_delta = _stream->get_u2(CHECK_NULL); 366 367 if (frame_type < EARLY_LARVAL) { 368 // reserved frame types 369 _stream->stackmap_format_error( 370 "reserved frame type", CHECK_VERIFY_(_verifier, nullptr)); 371 } 372 373 if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 374 // same_locals_1_stack_item_frame_extended 375 if (_first) { 376 offset = offset_delta; 377 // Can't share the locals array since that is updated by the verifier. 378 if (_prev_frame->locals_size() > 0) { 379 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 380 THREAD, VerificationType, _prev_frame->locals_size()); 381 } 382 } else { 383 offset = _prev_frame->offset() + offset_delta + 1; 384 locals = _prev_frame->locals(); 385 } 386 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 387 THREAD, VerificationType, 2); 388 u2 stack_size = 1; 389 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 390 if (stack[0].is_category2()) { 391 stack[1] = stack[0].to_category2_2nd(); 392 stack_size = 2; 393 } 394 check_verification_type_array_size( 395 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 396 frame = new StackMapFrame( 397 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 398 _max_locals, _max_stack, locals, stack, 399 _assert_unset_fields_buffer, _verifier); 400 if (_first && locals != nullptr) { 401 frame->copy_locals(_prev_frame); 402 } 403 _first = false; 404 return frame; 405 } 406 407 if (frame_type <= SAME_EXTENDED) { 408 // chop_frame or same_frame_extended 409 locals = _prev_frame->locals(); 410 int length = _prev_frame->locals_size(); 411 int chops = SAME_EXTENDED - frame_type; 412 int new_length = length; 413 u1 flags = _prev_frame->flags(); 414 if (chops != 0) { 415 new_length = chop(locals, length, chops); 416 check_verification_type_array_size( 417 new_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 418 // Recompute flags since uninitializedThis could have been chopped. 419 flags = 0; 420 for (int i=0; i<new_length; i++) { 421 if (locals[i].is_uninitialized_this()) { 422 flags |= FLAG_THIS_UNINIT; 423 break; 424 } 425 } 426 } 427 if (_first) { 428 offset = offset_delta; 429 // Can't share the locals array since that is updated by the verifier. 430 if (new_length > 0) { 431 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 432 THREAD, VerificationType, new_length); 433 } else { 434 locals = nullptr; 435 } 436 } else { 437 offset = _prev_frame->offset() + offset_delta + 1; 438 } 439 frame = new StackMapFrame( 440 offset, flags, new_length, 0, _max_locals, _max_stack, 441 locals, nullptr, 442 _assert_unset_fields_buffer, _verifier); 443 if (_first && locals != nullptr) { 444 frame->copy_locals(_prev_frame); 445 } 446 _first = false; 447 return frame; 448 } else if (frame_type < SAME_EXTENDED + 4) { 449 // append_frame 450 int appends = frame_type - SAME_EXTENDED; 451 int real_length = _prev_frame->locals_size(); 452 int new_length = real_length + appends*2; 453 locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length); 454 VerificationType* pre_locals = _prev_frame->locals(); 455 for (int i = 0; i < _prev_frame->locals_size(); i++) { 456 locals[i] = pre_locals[i]; 457 } 458 u1 flags = _prev_frame->flags(); 459 for (int i = 0; i < appends; i++) { 460 locals[real_length] = parse_verification_type(&flags, CHECK_NULL); 461 if (locals[real_length].is_category2()) { 462 locals[real_length + 1] = locals[real_length].to_category2_2nd(); 463 ++real_length; 464 } 465 ++real_length; 466 } 467 check_verification_type_array_size( 468 real_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 469 if (_first) { 470 offset = offset_delta; 471 } else { 472 offset = _prev_frame->offset() + offset_delta + 1; 473 } 474 frame = new StackMapFrame( 475 offset, flags, real_length, 0, _max_locals, 476 _max_stack, locals, nullptr, 477 _assert_unset_fields_buffer, _verifier); 478 _first = false; 479 return frame; 480 } 481 if (frame_type == FULL) { 482 // full_frame 483 u1 flags = 0; 484 u2 locals_size = _stream->get_u2(CHECK_NULL); 485 int real_locals_size = 0; 486 if (locals_size > 0) { 487 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 488 THREAD, VerificationType, locals_size*2); 489 } 490 for (int i = 0; i < locals_size; i++) { 491 locals[real_locals_size] = parse_verification_type(&flags, CHECK_NULL); 492 if (locals[real_locals_size].is_category2()) { 493 locals[real_locals_size + 1] = 494 locals[real_locals_size].to_category2_2nd(); 495 ++real_locals_size; 496 } 497 ++real_locals_size; 498 } 499 check_verification_type_array_size( 500 real_locals_size, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 501 u2 stack_size = _stream->get_u2(CHECK_NULL); 502 int real_stack_size = 0; 503 VerificationType* stack = nullptr; 504 if (stack_size > 0) { 505 stack = NEW_RESOURCE_ARRAY_IN_THREAD( 506 THREAD, VerificationType, stack_size*2); 507 } 508 for (int i = 0; i < stack_size; i++) { 509 stack[real_stack_size] = parse_verification_type(nullptr, CHECK_NULL); 510 if (stack[real_stack_size].is_category2()) { 511 stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(); 512 ++real_stack_size; 513 } 514 ++real_stack_size; 515 } 516 check_verification_type_array_size( 517 real_stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 518 if (_first) { 519 offset = offset_delta; 520 } else { 521 offset = _prev_frame->offset() + offset_delta + 1; 522 } 523 frame = new StackMapFrame( 524 offset, flags, real_locals_size, real_stack_size, 525 _max_locals, _max_stack, locals, stack, 526 _assert_unset_fields_buffer, _verifier); 527 _first = false; 528 return frame; 529 } 530 531 _stream->stackmap_format_error( 532 "reserved frame type", CHECK_VERIFY_(_prev_frame->verifier(), nullptr)); 533 return nullptr; 534 }