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 } 131 return result; 132 } 133 134 void StackMapTable::check_jump_target( 135 StackMapFrame* frame, int32_t target, TRAPS) const { 136 ErrorContext ctx; 137 bool match = match_stackmap( 138 frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); 139 if (!match || (target < 0 || target >= _code_length)) { 140 frame->verifier()->verify_error(ctx, 141 "Inconsistent stackmap frames at branch target %d", target); 142 } 143 } 144 145 void StackMapTable::print_on(outputStream* str) const { 146 str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count); 147 str->indent().print_cr("table = { "); 148 { 149 streamIndentor si(str); 150 for (int32_t i = 0; i < _frame_count; ++i) { 151 _frame_array->at(i)->print_on(str); 152 } 153 } 154 str->print_cr(" }"); 155 } 156 157 StackMapReader::StackMapReader(ClassVerifier* v, StackMapStream* stream, 158 char* code_data, int32_t code_len, 159 StackMapFrame* init_frame, 160 u2 max_locals, u2 max_stack, TRAPS) : 161 _verifier(v), _stream(stream), _code_data(code_data), 162 _code_length(code_len), _parsed_frame_count(0), 163 _prev_frame(init_frame), _max_locals(max_locals), 164 _max_stack(max_stack), _first(true) { 165 methodHandle m = v->method(); 166 if (m->has_stackmap_table()) { 167 _cp = constantPoolHandle(THREAD, m->constants()); 168 _frame_count = _stream->get_u2(CHECK); 169 } else { 170 // There's no stackmap table present. Frame count and size are 0. 171 _frame_count = 0; 172 } 173 } 174 175 int32_t StackMapReader::chop( 176 VerificationType* locals, int32_t length, int32_t chops) { 177 if (locals == nullptr) return -1; 178 int32_t pos = length - 1; 179 for (int32_t i=0; i<chops; i++) { 180 if (locals[pos].is_category2_2nd()) { 181 pos -= 2; 182 } else { 183 pos --; 184 } 185 if (pos<0 && i<(chops-1)) return -1; 186 } 187 return pos+1; 188 } 189 190 #define CHECK_NT CHECK_(VerificationType::bogus_type()) 191 192 VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) { 193 u1 tag = _stream->get_u1(CHECK_NT); 194 if (tag < (u1)ITEM_UninitializedThis) { 195 return VerificationType::from_tag(tag); 196 } 197 if (tag == ITEM_Object) { 198 u2 class_index = _stream->get_u2(CHECK_NT); 199 int nconstants = _cp->length(); 200 if ((class_index <= 0 || class_index >= nconstants) || 201 (!_cp->tag_at(class_index).is_klass() && 202 !_cp->tag_at(class_index).is_unresolved_klass())) { 203 _stream->stackmap_format_error("bad class index", THREAD); 204 return VerificationType::bogus_type(); 205 } 206 return VerificationType::reference_type(_cp->klass_name_at(class_index)); 207 } 208 if (tag == ITEM_UninitializedThis) { 209 if (flags != nullptr) { 210 *flags |= FLAG_THIS_UNINIT; 211 } 212 return VerificationType::uninitialized_this_type(); 213 } 214 if (tag == ITEM_Uninitialized) { 215 u2 offset = _stream->get_u2(CHECK_NT); 216 if (offset >= _code_length || 217 _code_data[offset] != ClassVerifier::NEW_OFFSET) { 218 _verifier->class_format_error( 219 "StackMapTable format error: bad offset for Uninitialized"); 220 return VerificationType::bogus_type(); 221 } 222 return VerificationType::uninitialized_type(offset); 223 } 224 _stream->stackmap_format_error("bad verification type", THREAD); 225 return VerificationType::bogus_type(); 226 } 227 228 StackMapFrame* StackMapReader::next(TRAPS) { 229 _parsed_frame_count++; 230 check_size(CHECK_NULL); 231 StackMapFrame* frame = next_helper(CHECK_VERIFY_(_verifier, nullptr)); 232 if (frame != nullptr) { 233 check_offset(frame); 234 if (frame->verifier()->has_error()) { 235 return nullptr; 236 } 237 _prev_frame = frame; 238 } 239 return frame; 240 } 241 242 StackMapFrame* StackMapReader::next_helper(TRAPS) { 243 StackMapFrame* frame; 244 int offset; 245 VerificationType* locals = nullptr; 246 u1 frame_type = _stream->get_u1(CHECK_NULL); 247 if (frame_type < 64) { 248 // same_frame 249 if (_first) { 250 offset = frame_type; 251 // Can't share the locals array since that is updated by the verifier. 252 if (_prev_frame->locals_size() > 0) { 253 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 254 THREAD, VerificationType, _prev_frame->locals_size()); 255 } 256 } else { 257 offset = _prev_frame->offset() + frame_type + 1; 258 locals = _prev_frame->locals(); 259 } 260 frame = new StackMapFrame( 261 offset, _prev_frame->flags(), _prev_frame->locals_size(), 0, 262 _max_locals, _max_stack, locals, nullptr, _verifier); 263 if (_first && locals != nullptr) { 264 frame->copy_locals(_prev_frame); 265 } 266 _first = false; 267 return frame; 268 } 269 if (frame_type < 128) { 270 // same_locals_1_stack_item_frame 271 if (_first) { 272 offset = frame_type - 64; 273 // Can't share the locals array since that is updated by the verifier. 274 if (_prev_frame->locals_size() > 0) { 275 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 276 THREAD, VerificationType, _prev_frame->locals_size()); 277 } 278 } else { 279 offset = _prev_frame->offset() + frame_type - 63; 280 locals = _prev_frame->locals(); 281 } 282 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 283 THREAD, VerificationType, 2); 284 u2 stack_size = 1; 285 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 286 if (stack[0].is_category2()) { 287 stack[1] = stack[0].to_category2_2nd(); 288 stack_size = 2; 289 } 290 check_verification_type_array_size( 291 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 292 frame = new StackMapFrame( 293 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 294 _max_locals, _max_stack, locals, stack, _verifier); 295 if (_first && locals != nullptr) { 296 frame->copy_locals(_prev_frame); 297 } 298 _first = false; 299 return frame; 300 } 301 302 u2 offset_delta = _stream->get_u2(CHECK_NULL); 303 304 if (frame_type < SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 305 // reserved frame types 306 _stream->stackmap_format_error( 307 "reserved frame type", CHECK_VERIFY_(_verifier, nullptr)); 308 } 309 310 if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 311 // same_locals_1_stack_item_frame_extended 312 if (_first) { 313 offset = offset_delta; 314 // Can't share the locals array since that is updated by the verifier. 315 if (_prev_frame->locals_size() > 0) { 316 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 317 THREAD, VerificationType, _prev_frame->locals_size()); 318 } 319 } else { 320 offset = _prev_frame->offset() + offset_delta + 1; 321 locals = _prev_frame->locals(); 322 } 323 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 324 THREAD, VerificationType, 2); 325 u2 stack_size = 1; 326 stack[0] = parse_verification_type(nullptr, CHECK_VERIFY_(_verifier, nullptr)); 327 if (stack[0].is_category2()) { 328 stack[1] = stack[0].to_category2_2nd(); 329 stack_size = 2; 330 } 331 check_verification_type_array_size( 332 stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 333 frame = new StackMapFrame( 334 offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size, 335 _max_locals, _max_stack, locals, stack, _verifier); 336 if (_first && locals != nullptr) { 337 frame->copy_locals(_prev_frame); 338 } 339 _first = false; 340 return frame; 341 } 342 343 if (frame_type <= SAME_EXTENDED) { 344 // chop_frame or same_frame_extended 345 locals = _prev_frame->locals(); 346 int length = _prev_frame->locals_size(); 347 int chops = SAME_EXTENDED - frame_type; 348 int new_length = length; 349 u1 flags = _prev_frame->flags(); 350 if (chops != 0) { 351 new_length = chop(locals, length, chops); 352 check_verification_type_array_size( 353 new_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 354 // Recompute flags since uninitializedThis could have been chopped. 355 flags = 0; 356 for (int i=0; i<new_length; i++) { 357 if (locals[i].is_uninitialized_this()) { 358 flags |= FLAG_THIS_UNINIT; 359 break; 360 } 361 } 362 } 363 if (_first) { 364 offset = offset_delta; 365 // Can't share the locals array since that is updated by the verifier. 366 if (new_length > 0) { 367 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 368 THREAD, VerificationType, new_length); 369 } else { 370 locals = nullptr; 371 } 372 } else { 373 offset = _prev_frame->offset() + offset_delta + 1; 374 } 375 frame = new StackMapFrame( 376 offset, flags, new_length, 0, _max_locals, _max_stack, 377 locals, nullptr, _verifier); 378 if (_first && locals != nullptr) { 379 frame->copy_locals(_prev_frame); 380 } 381 _first = false; 382 return frame; 383 } else if (frame_type < SAME_EXTENDED + 4) { 384 // append_frame 385 int appends = frame_type - SAME_EXTENDED; 386 int real_length = _prev_frame->locals_size(); 387 int new_length = real_length + appends*2; 388 locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length); 389 VerificationType* pre_locals = _prev_frame->locals(); 390 for (int i = 0; i < _prev_frame->locals_size(); i++) { 391 locals[i] = pre_locals[i]; 392 } 393 u1 flags = _prev_frame->flags(); 394 for (int i = 0; i < appends; i++) { 395 locals[real_length] = parse_verification_type(&flags, CHECK_NULL); 396 if (locals[real_length].is_category2()) { 397 locals[real_length + 1] = locals[real_length].to_category2_2nd(); 398 ++real_length; 399 } 400 ++real_length; 401 } 402 check_verification_type_array_size( 403 real_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 404 if (_first) { 405 offset = offset_delta; 406 } else { 407 offset = _prev_frame->offset() + offset_delta + 1; 408 } 409 frame = new StackMapFrame( 410 offset, flags, real_length, 0, _max_locals, 411 _max_stack, locals, nullptr, _verifier); 412 _first = false; 413 return frame; 414 } 415 if (frame_type == FULL) { 416 // full_frame 417 u1 flags = 0; 418 u2 locals_size = _stream->get_u2(CHECK_NULL); 419 int real_locals_size = 0; 420 if (locals_size > 0) { 421 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 422 THREAD, VerificationType, locals_size*2); 423 } 424 for (int i = 0; i < locals_size; i++) { 425 locals[real_locals_size] = parse_verification_type(&flags, CHECK_NULL); 426 if (locals[real_locals_size].is_category2()) { 427 locals[real_locals_size + 1] = 428 locals[real_locals_size].to_category2_2nd(); 429 ++real_locals_size; 430 } 431 ++real_locals_size; 432 } 433 check_verification_type_array_size( 434 real_locals_size, _max_locals, CHECK_VERIFY_(_verifier, nullptr)); 435 u2 stack_size = _stream->get_u2(CHECK_NULL); 436 int real_stack_size = 0; 437 VerificationType* stack = nullptr; 438 if (stack_size > 0) { 439 stack = NEW_RESOURCE_ARRAY_IN_THREAD( 440 THREAD, VerificationType, stack_size*2); 441 } 442 for (int i = 0; i < stack_size; i++) { 443 stack[real_stack_size] = parse_verification_type(nullptr, CHECK_NULL); 444 if (stack[real_stack_size].is_category2()) { 445 stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(); 446 ++real_stack_size; 447 } 448 ++real_stack_size; 449 } 450 check_verification_type_array_size( 451 real_stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr)); 452 if (_first) { 453 offset = offset_delta; 454 } else { 455 offset = _prev_frame->offset() + offset_delta + 1; 456 } 457 frame = new StackMapFrame( 458 offset, flags, real_locals_size, real_stack_size, 459 _max_locals, _max_stack, locals, stack, _verifier); 460 _first = false; 461 return frame; 462 } 463 464 _stream->stackmap_format_error( 465 "reserved frame type", CHECK_VERIFY_(_prev_frame->verifier(), nullptr)); 466 return nullptr; 467 } --- EOF ---