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 == ASSERT_UNSET_FIELDS) { 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 return nullptr; 283 } 284 if (frame_type < 64) { 285 // same_frame 286 if (_first) { 287 offset = frame_type; 288 // Can't share the locals array since that is updated by the verifier. 289 if (_prev_frame->locals_size() > 0) { 290 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 291 THREAD, VerificationType, _prev_frame->locals_size()); 292 } 293 } else { 294 offset = _prev_frame->offset() + frame_type + 1; 295 locals = _prev_frame->locals(); 296 } 297 frame = new StackMapFrame( 298 offset, _prev_frame->flags(), _prev_frame->locals_size(), 0, 299 _max_locals, _max_stack, locals, nullptr, 300 _assert_unset_fields_buffer, _verifier); 301 if (_first && locals != nullptr) { 302 frame->copy_locals(_prev_frame); 303 } 304 _first = false; 305 return frame; 306 } 307 if (frame_type < 128) { 308 // same_locals_1_stack_item_frame 309 if (_first) { 310 offset = frame_type - 64; 311 // Can't share the locals array since that is updated by the verifier. 312 if (_prev_frame->locals_size() > 0) { 313 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 314 THREAD, VerificationType, _prev_frame->locals_size()); 315 } 316 } else { 317 offset = _prev_frame->offset() + frame_type - 63; 318 locals = _prev_frame->locals(); 319 } 320 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 321 THREAD, VerificationType, 2); 322 u2 stack_size = 1; 323 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 324 if (stack[0].is_category2()) { 325 stack[1] = stack[0].to_category2_2nd(); 326 stack_size = 2; 327 } 328 check_verification_type_array_size( 329 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 330 frame = new StackMapFrame( 331 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 332 _max_locals, _max_stack, locals, stack, 333 _assert_unset_fields_buffer, _verifier); 334 if (_first && locals != nullptr) { 335 frame->copy_locals(_prev_frame); 336 } 337 _first = false; 338 return frame; 339 } 340 341 u2 offset_delta = _stream->get_u2(CHECK_NULL); 342 343 if (frame_type < ASSERT_UNSET_FIELDS) { 344 // reserved frame types 345 _stream->stackmap_format_error( 346 "reserved frame type", CHECK_VERIFY_(_verifier, nullptr)); 347 } 348 349 if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 350 // same_locals_1_stack_item_frame_extended 351 if (_first) { 352 offset = offset_delta; 353 // Can't share the locals array since that is updated by the verifier. 354 if (_prev_frame->locals_size() > 0) { 355 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 356 THREAD, VerificationType, _prev_frame->locals_size()); 357 } 358 } else { 359 offset = _prev_frame->offset() + offset_delta + 1; 360 locals = _prev_frame->locals(); 361 } 362 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 363 THREAD, VerificationType, 2); 364 u2 stack_size = 1; 365 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 366 if (stack[0].is_category2()) { 367 stack[1] = stack[0].to_category2_2nd(); 368 stack_size = 2; 369 } 370 check_verification_type_array_size( 371 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 372 frame = new StackMapFrame( 373 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 374 _max_locals, _max_stack, locals, stack, 375 _assert_unset_fields_buffer, _verifier); 376 if (_first && locals != nullptr) { 377 frame->copy_locals(_prev_frame); 378 } 379 _first = false; 380 return frame; 381 } 382 383 if (frame_type <= SAME_EXTENDED) { 384 // chop_frame or same_frame_extended 385 locals = _prev_frame->locals(); 386 int length = _prev_frame->locals_size(); 387 int chops = SAME_EXTENDED - frame_type; 388 int new_length = length; 389 u1 flags = _prev_frame->flags(); 390 if (chops != 0) { 391 new_length = chop(locals, length, chops); 392 check_verification_type_array_size( 393 new_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 394 // Recompute flags since uninitializedThis could have been chopped. 395 flags = 0; 396 for (int i=0; i<new_length; i++) { 397 if (locals[i].is_uninitialized_this()) { 398 flags |= FLAG_THIS_UNINIT; 399 break; 400 } 401 } 402 } 403 if (_first) { 404 offset = offset_delta; 405 // Can't share the locals array since that is updated by the verifier. 406 if (new_length > 0) { 407 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 408 THREAD, VerificationType, new_length); 409 } else { 410 locals = nullptr; 411 } 412 } else { 413 offset = _prev_frame->offset() + offset_delta + 1; 414 } 415 frame = new StackMapFrame( 416 offset, flags, new_length, 0, _max_locals, _max_stack, 417 locals, nullptr, 418 _assert_unset_fields_buffer, _verifier); 419 if (_first && locals != nullptr) { 420 frame->copy_locals(_prev_frame); 421 } 422 _first = false; 423 return frame; 424 } else if (frame_type < SAME_EXTENDED + 4) { 425 // append_frame 426 int appends = frame_type - SAME_EXTENDED; 427 int real_length = _prev_frame->locals_size(); 428 int new_length = real_length + appends*2; 429 locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length); 430 VerificationType* pre_locals = _prev_frame->locals(); 431 for (int i = 0; i < _prev_frame->locals_size(); i++) { 432 locals[i] = pre_locals[i]; 433 } 434 u1 flags = _prev_frame->flags(); 435 for (int i = 0; i < appends; i++) { 436 locals[real_length] = parse_verification_type(&flags, CHECK_NULL); 437 if (locals[real_length].is_category2()) { 438 locals[real_length + 1] = locals[real_length].to_category2_2nd(); 439 ++real_length; 440 } 441 ++real_length; 442 } 443 check_verification_type_array_size( 444 real_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 445 if (_first) { 446 offset = offset_delta; 447 } else { 448 offset = _prev_frame->offset() + offset_delta + 1; 449 } 450 frame = new StackMapFrame( 451 offset, flags, real_length, 0, _max_locals, 452 _max_stack, locals, nullptr, 453 _assert_unset_fields_buffer, _verifier); 454 _first = false; 455 return frame; 456 } 457 if (frame_type == FULL) { 458 // full_frame 459 u1 flags = 0; 460 u2 locals_size = _stream->get_u2(CHECK_NULL); 461 int real_locals_size = 0; 462 if (locals_size > 0) { 463 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 464 THREAD, VerificationType, locals_size*2); 465 } 466 for (int i = 0; i < locals_size; i++) { 467 locals[real_locals_size] = parse_verification_type(&flags, CHECK_NULL); 468 if (locals[real_locals_size].is_category2()) { 469 locals[real_locals_size + 1] = 470 locals[real_locals_size].to_category2_2nd(); 471 ++real_locals_size; 472 } 473 ++real_locals_size; 474 } 475 check_verification_type_array_size( 476 real_locals_size, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 477 u2 stack_size = _stream->get_u2(CHECK_NULL); 478 int real_stack_size = 0; 479 VerificationType* stack = nullptr; 480 if (stack_size > 0) { 481 stack = NEW_RESOURCE_ARRAY_IN_THREAD( 482 THREAD, VerificationType, stack_size*2); 483 } 484 for (int i = 0; i < stack_size; i++) { 485 stack[real_stack_size] = parse_verification_type(nullptr, CHECK_NULL); 486 if (stack[real_stack_size].is_category2()) { 487 stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(); 488 ++real_stack_size; 489 } 490 ++real_stack_size; 491 } 492 check_verification_type_array_size( 493 real_stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 494 if (_first) { 495 offset = offset_delta; 496 } else { 497 offset = _prev_frame->offset() + offset_delta + 1; 498 } 499 frame = new StackMapFrame( 500 offset, flags, real_locals_size, real_stack_size, 501 _max_locals, _max_stack, locals, stack, 502 _assert_unset_fields_buffer, _verifier); 503 _first = false; 504 return frame; 505 } 506 507 _stream->stackmap_format_error( 508 "reserved frame type", CHECK_VERIFY_(_prev_frame->verifier(), nullptr)); 509 return nullptr; 510 }