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 Symbol* name = _cp->symbol_at(_cp->name_ref_index_at(index)); 258 Symbol* sig = _cp->symbol_at(_cp->signature_ref_index_at(index)); 259 NameAndSig tmp(name, sig); 260 261 if (!_prev_frame->assert_unset_fields()->contains(tmp)) { 262 ResourceMark rm(THREAD); 263 log_info(verification)("Field %s%s is not found among initial strict instance fields", name->as_C_string(), sig->as_C_string()); 264 StackMapFrame::print_strict_fields(_prev_frame->assert_unset_fields()); 265 _prev_frame->verifier()->verify_error( 266 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 267 "Strict fields not a subset of initial strict instance fields: %s:%s", name->as_C_string(), sig->as_C_string()); 268 } else { 269 new_fields->put(tmp, false); 270 } 271 } 272 273 // Only modify strict instance fields the frame has uninitialized this 274 if (_prev_frame->flag_this_uninit()) { 275 _assert_unset_fields_buffer = _prev_frame->merge_unset_fields(new_fields); 276 } else if (new_fields->number_of_entries() > 0) { 277 _prev_frame->verifier()->verify_error( 278 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 279 "Cannot have uninitialized strict fields after class initialization"); 280 } 281 282 // Continue reading frame data 283 if (at_end()) { 284 _prev_frame->verifier()->verify_error( 285 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 286 "Early larval frame must be followed by a base frame"); 287 } 288 289 frame_type = _stream->get_u1(CHECK_NULL); 290 if (frame_type == EARLY_LARVAL) { 291 _prev_frame->verifier()->verify_error( 292 ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame), 293 "Early larval frame must be followed by a base frame"); 294 } 295 } 296 297 if (frame_type < 64) { 298 // same_frame 299 if (_first) { 300 offset = frame_type; 301 // Can't share the locals array since that is updated by the verifier. 302 if (_prev_frame->locals_size() > 0) { 303 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 304 THREAD, VerificationType, _prev_frame->locals_size()); 305 } 306 } else { 307 offset = _prev_frame->offset() + frame_type + 1; 308 locals = _prev_frame->locals(); 309 } 310 frame = new StackMapFrame( 311 offset, _prev_frame->flags(), _prev_frame->locals_size(), 0, 312 _max_locals, _max_stack, locals, nullptr, 313 _assert_unset_fields_buffer, _verifier); 314 if (_first && locals != nullptr) { 315 frame->copy_locals(_prev_frame); 316 } 317 _first = false; 318 return frame; 319 } 320 if (frame_type < 128) { 321 // same_locals_1_stack_item_frame 322 if (_first) { 323 offset = frame_type - 64; 324 // Can't share the locals array since that is updated by the verifier. 325 if (_prev_frame->locals_size() > 0) { 326 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 327 THREAD, VerificationType, _prev_frame->locals_size()); 328 } 329 } else { 330 offset = _prev_frame->offset() + frame_type - 63; 331 locals = _prev_frame->locals(); 332 } 333 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 334 THREAD, VerificationType, 2); 335 u2 stack_size = 1; 336 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 337 if (stack[0].is_category2()) { 338 stack[1] = stack[0].to_category2_2nd(); 339 stack_size = 2; 340 } 341 check_verification_type_array_size( 342 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 343 frame = new StackMapFrame( 344 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 345 _max_locals, _max_stack, locals, stack, 346 _assert_unset_fields_buffer, _verifier); 347 if (_first && locals != nullptr) { 348 frame->copy_locals(_prev_frame); 349 } 350 _first = false; 351 return frame; 352 } 353 354 u2 offset_delta = _stream->get_u2(CHECK_NULL); 355 356 if (frame_type < EARLY_LARVAL) { 357 // reserved frame types 358 _stream->stackmap_format_error( 359 "reserved frame type", CHECK_VERIFY_(_verifier, nullptr)); 360 } 361 362 if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 363 // same_locals_1_stack_item_frame_extended 364 if (_first) { 365 offset = offset_delta; 366 // Can't share the locals array since that is updated by the verifier. 367 if (_prev_frame->locals_size() > 0) { 368 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 369 THREAD, VerificationType, _prev_frame->locals_size()); 370 } 371 } else { 372 offset = _prev_frame->offset() + offset_delta + 1; 373 locals = _prev_frame->locals(); 374 } 375 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 376 THREAD, VerificationType, 2); 377 u2 stack_size = 1; 378 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 379 if (stack[0].is_category2()) { 380 stack[1] = stack[0].to_category2_2nd(); 381 stack_size = 2; 382 } 383 check_verification_type_array_size( 384 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 385 frame = new StackMapFrame( 386 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 387 _max_locals, _max_stack, locals, stack, 388 _assert_unset_fields_buffer, _verifier); 389 if (_first && locals != nullptr) { 390 frame->copy_locals(_prev_frame); 391 } 392 _first = false; 393 return frame; 394 } 395 396 if (frame_type <= SAME_EXTENDED) { 397 // chop_frame or same_frame_extended 398 locals = _prev_frame->locals(); 399 int length = _prev_frame->locals_size(); 400 int chops = SAME_EXTENDED - frame_type; 401 int new_length = length; 402 u1 flags = _prev_frame->flags(); 403 if (chops != 0) { 404 new_length = chop(locals, length, chops); 405 check_verification_type_array_size( 406 new_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 407 // Recompute flags since uninitializedThis could have been chopped. 408 flags = 0; 409 for (int i=0; i<new_length; i++) { 410 if (locals[i].is_uninitialized_this()) { 411 flags |= FLAG_THIS_UNINIT; 412 break; 413 } 414 } 415 } 416 if (_first) { 417 offset = offset_delta; 418 // Can't share the locals array since that is updated by the verifier. 419 if (new_length > 0) { 420 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 421 THREAD, VerificationType, new_length); 422 } else { 423 locals = nullptr; 424 } 425 } else { 426 offset = _prev_frame->offset() + offset_delta + 1; 427 } 428 frame = new StackMapFrame( 429 offset, flags, new_length, 0, _max_locals, _max_stack, 430 locals, nullptr, 431 _assert_unset_fields_buffer, _verifier); 432 if (_first && locals != nullptr) { 433 frame->copy_locals(_prev_frame); 434 } 435 _first = false; 436 return frame; 437 } else if (frame_type < SAME_EXTENDED + 4) { 438 // append_frame 439 int appends = frame_type - SAME_EXTENDED; 440 int real_length = _prev_frame->locals_size(); 441 int new_length = real_length + appends*2; 442 locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length); 443 VerificationType* pre_locals = _prev_frame->locals(); 444 for (int i = 0; i < _prev_frame->locals_size(); i++) { 445 locals[i] = pre_locals[i]; 446 } 447 u1 flags = _prev_frame->flags(); 448 for (int i = 0; i < appends; i++) { 449 locals[real_length] = parse_verification_type(&flags, CHECK_NULL); 450 if (locals[real_length].is_category2()) { 451 locals[real_length + 1] = locals[real_length].to_category2_2nd(); 452 ++real_length; 453 } 454 ++real_length; 455 } 456 check_verification_type_array_size( 457 real_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 458 if (_first) { 459 offset = offset_delta; 460 } else { 461 offset = _prev_frame->offset() + offset_delta + 1; 462 } 463 frame = new StackMapFrame( 464 offset, flags, real_length, 0, _max_locals, 465 _max_stack, locals, nullptr, 466 _assert_unset_fields_buffer, _verifier); 467 _first = false; 468 return frame; 469 } 470 if (frame_type == FULL) { 471 // full_frame 472 u1 flags = 0; 473 u2 locals_size = _stream->get_u2(CHECK_NULL); 474 int real_locals_size = 0; 475 if (locals_size > 0) { 476 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 477 THREAD, VerificationType, locals_size*2); 478 } 479 for (int i = 0; i < locals_size; i++) { 480 locals[real_locals_size] = parse_verification_type(&flags, CHECK_NULL); 481 if (locals[real_locals_size].is_category2()) { 482 locals[real_locals_size + 1] = 483 locals[real_locals_size].to_category2_2nd(); 484 ++real_locals_size; 485 } 486 ++real_locals_size; 487 } 488 check_verification_type_array_size( 489 real_locals_size, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 490 u2 stack_size = _stream->get_u2(CHECK_NULL); 491 int real_stack_size = 0; 492 VerificationType* stack = nullptr; 493 if (stack_size > 0) { 494 stack = NEW_RESOURCE_ARRAY_IN_THREAD( 495 THREAD, VerificationType, stack_size*2); 496 } 497 for (int i = 0; i < stack_size; i++) { 498 stack[real_stack_size] = parse_verification_type(nullptr, CHECK_NULL); 499 if (stack[real_stack_size].is_category2()) { 500 stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(); 501 ++real_stack_size; 502 } 503 ++real_stack_size; 504 } 505 check_verification_type_array_size( 506 real_stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 507 if (_first) { 508 offset = offset_delta; 509 } else { 510 offset = _prev_frame->offset() + offset_delta + 1; 511 } 512 frame = new StackMapFrame( 513 offset, flags, real_locals_size, real_stack_size, 514 _max_locals, _max_stack, locals, stack, 515 _assert_unset_fields_buffer, _verifier); 516 _first = false; 517 return frame; 518 } 519 520 _stream->stackmap_format_error( 521 "reserved frame type", CHECK_VERIFY_(_prev_frame->verifier(), nullptr)); 522 return nullptr; 523 }