Skip to content

Commit 3f884a9

Browse files
committed
8364660: ClassVerifier::ends_in_athrow() should be removed
Reviewed-by: phh Backport-of: 6a9bd7781ce1ddbc90712b00fd940c4ce697a1fe
1 parent 1303000 commit 3f884a9

File tree

2 files changed

+1
-241
lines changed

2 files changed

+1
-241
lines changed

src/hotspot/share/classfile/verifier.cpp

Lines changed: 0 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,216 +2439,6 @@ void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs,
24392439
}
24402440
}
24412441

2442-
// Look at the method's handlers. If the bci is in the handler's try block
2443-
// then check if the handler_pc is already on the stack. If not, push it
2444-
// unless the handler has already been scanned.
2445-
void ClassVerifier::push_handlers(ExceptionTable* exhandlers,
2446-
GrowableArray<u4>* handler_list,
2447-
GrowableArray<u4>* handler_stack,
2448-
u4 bci) {
2449-
int exlength = exhandlers->length();
2450-
for(int x = 0; x < exlength; x++) {
2451-
if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) {
2452-
u4 exhandler_pc = exhandlers->handler_pc(x);
2453-
if (!handler_list->contains(exhandler_pc)) {
2454-
handler_stack->append_if_missing(exhandler_pc);
2455-
handler_list->append(exhandler_pc);
2456-
}
2457-
}
2458-
}
2459-
}
2460-
2461-
// Return TRUE if all code paths starting with start_bc_offset end in
2462-
// bytecode athrow or loop.
2463-
bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
2464-
ResourceMark rm;
2465-
// Create bytecode stream.
2466-
RawBytecodeStream bcs(method());
2467-
u4 code_length = method()->code_size();
2468-
bcs.set_start(start_bc_offset);
2469-
u4 target;
2470-
// Create stack for storing bytecode start offsets for if* and *switch.
2471-
GrowableArray<u4>* bci_stack = new GrowableArray<u4>(30);
2472-
// Create stack for handlers for try blocks containing this handler.
2473-
GrowableArray<u4>* handler_stack = new GrowableArray<u4>(30);
2474-
// Create list of handlers that have been pushed onto the handler_stack
2475-
// so that handlers embedded inside of their own TRY blocks only get
2476-
// scanned once.
2477-
GrowableArray<u4>* handler_list = new GrowableArray<u4>(30);
2478-
// Create list of visited branch opcodes (goto* and if*).
2479-
GrowableArray<u4>* visited_branches = new GrowableArray<u4>(30);
2480-
ExceptionTable exhandlers(_method());
2481-
2482-
while (true) {
2483-
if (bcs.is_last_bytecode()) {
2484-
// if no more starting offsets to parse or if at the end of the
2485-
// method then return false.
2486-
if ((bci_stack->is_empty()) || ((u4)bcs.end_bci() == code_length))
2487-
return false;
2488-
// Pop a bytecode starting offset and scan from there.
2489-
bcs.set_start(bci_stack->pop());
2490-
}
2491-
Bytecodes::Code opcode = bcs.raw_next();
2492-
u4 bci = bcs.bci();
2493-
2494-
// If the bytecode is in a TRY block, push its handlers so they
2495-
// will get parsed.
2496-
push_handlers(&exhandlers, handler_list, handler_stack, bci);
2497-
2498-
switch (opcode) {
2499-
case Bytecodes::_if_icmpeq:
2500-
case Bytecodes::_if_icmpne:
2501-
case Bytecodes::_if_icmplt:
2502-
case Bytecodes::_if_icmpge:
2503-
case Bytecodes::_if_icmpgt:
2504-
case Bytecodes::_if_icmple:
2505-
case Bytecodes::_ifeq:
2506-
case Bytecodes::_ifne:
2507-
case Bytecodes::_iflt:
2508-
case Bytecodes::_ifge:
2509-
case Bytecodes::_ifgt:
2510-
case Bytecodes::_ifle:
2511-
case Bytecodes::_if_acmpeq:
2512-
case Bytecodes::_if_acmpne:
2513-
case Bytecodes::_ifnull:
2514-
case Bytecodes::_ifnonnull:
2515-
target = bcs.dest();
2516-
if (visited_branches->contains(bci)) {
2517-
if (bci_stack->is_empty()) {
2518-
if (handler_stack->is_empty()) {
2519-
return true;
2520-
} else {
2521-
// Parse the catch handlers for try blocks containing athrow.
2522-
bcs.set_start(handler_stack->pop());
2523-
}
2524-
} else {
2525-
// Pop a bytecode starting offset and scan from there.
2526-
bcs.set_start(bci_stack->pop());
2527-
}
2528-
} else {
2529-
if (target > bci) { // forward branch
2530-
if (target >= code_length) return false;
2531-
// Push the branch target onto the stack.
2532-
bci_stack->push(target);
2533-
// then, scan bytecodes starting with next.
2534-
bcs.set_start(bcs.next_bci());
2535-
} else { // backward branch
2536-
// Push bytecode offset following backward branch onto the stack.
2537-
bci_stack->push(bcs.next_bci());
2538-
// Check bytecodes starting with branch target.
2539-
bcs.set_start(target);
2540-
}
2541-
// Record target so we don't branch here again.
2542-
visited_branches->append(bci);
2543-
}
2544-
break;
2545-
2546-
case Bytecodes::_goto:
2547-
case Bytecodes::_goto_w: {
2548-
int offset = (opcode == Bytecodes::_goto ? bcs.get_offset_s2() : bcs.get_offset_s4());
2549-
int min_offset = -1 * max_method_code_size;
2550-
// Check offset for overflow
2551-
if (offset < min_offset || offset > max_method_code_size) return false;
2552-
2553-
target = bci + offset;
2554-
if (visited_branches->contains(bci)) {
2555-
if (bci_stack->is_empty()) {
2556-
if (handler_stack->is_empty()) {
2557-
return true;
2558-
} else {
2559-
// Parse the catch handlers for try blocks containing athrow.
2560-
bcs.set_start(handler_stack->pop());
2561-
}
2562-
} else {
2563-
// Been here before, pop new starting offset from stack.
2564-
bcs.set_start(bci_stack->pop());
2565-
}
2566-
} else {
2567-
if (target >= code_length) return false;
2568-
// Continue scanning from the target onward.
2569-
bcs.set_start(target);
2570-
// Record target so we don't branch here again.
2571-
visited_branches->append(bci);
2572-
}
2573-
break;
2574-
}
2575-
2576-
// Check that all switch alternatives end in 'athrow' bytecodes. Since it
2577-
// is difficult to determine where each switch alternative ends, parse
2578-
// each switch alternative until either hit a 'return', 'athrow', or reach
2579-
// the end of the method's bytecodes. This is gross but should be okay
2580-
// because:
2581-
// 1. tableswitch and lookupswitch byte codes in handlers for ctor explicit
2582-
// constructor invocations should be rare.
2583-
// 2. if each switch alternative ends in an athrow then the parsing should be
2584-
// short. If there is no athrow then it is bogus code, anyway.
2585-
case Bytecodes::_lookupswitch:
2586-
case Bytecodes::_tableswitch:
2587-
{
2588-
address aligned_bcp = align_up(bcs.bcp() + 1, jintSize);
2589-
u4 default_offset = Bytes::get_Java_u4(aligned_bcp) + bci;
2590-
int keys, delta;
2591-
if (opcode == Bytecodes::_tableswitch) {
2592-
jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
2593-
jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
2594-
// This is invalid, but let the regular bytecode verifier
2595-
// report this because the user will get a better error message.
2596-
if (low > high) return true;
2597-
keys = high - low + 1;
2598-
delta = 1;
2599-
} else {
2600-
keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize);
2601-
delta = 2;
2602-
}
2603-
// Invalid, let the regular bytecode verifier deal with it.
2604-
if (keys < 0) return true;
2605-
2606-
// Push the offset of the next bytecode onto the stack.
2607-
bci_stack->push(bcs.next_bci());
2608-
2609-
// Push the switch alternatives onto the stack.
2610-
for (int i = 0; i < keys; i++) {
2611-
int min_offset = -1 * max_method_code_size;
2612-
int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
2613-
if (offset < min_offset || offset > max_method_code_size) return false;
2614-
u4 target = bci + offset;
2615-
if (target > code_length) return false;
2616-
bci_stack->push(target);
2617-
}
2618-
2619-
// Start bytecode parsing for the switch at the default alternative.
2620-
if (default_offset > code_length) return false;
2621-
bcs.set_start(default_offset);
2622-
break;
2623-
}
2624-
2625-
case Bytecodes::_return:
2626-
return false;
2627-
2628-
case Bytecodes::_athrow:
2629-
{
2630-
if (bci_stack->is_empty()) {
2631-
if (handler_stack->is_empty()) {
2632-
return true;
2633-
} else {
2634-
// Parse the catch handlers for try blocks containing athrow.
2635-
bcs.set_start(handler_stack->pop());
2636-
}
2637-
} else {
2638-
// Pop a bytecode offset and starting scanning from there.
2639-
bcs.set_start(bci_stack->pop());
2640-
}
2641-
}
2642-
break;
2643-
2644-
default:
2645-
;
2646-
} // end switch
2647-
} // end while loop
2648-
2649-
return false;
2650-
}
2651-
26522442
void ClassVerifier::verify_invoke_init(
26532443
RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
26542444
StackMapFrame* current_frame, u4 code_length, bool in_try_block,
@@ -2673,25 +2463,6 @@ void ClassVerifier::verify_invoke_init(
26732463
// sure that all catch clause paths end in a throw. Otherwise, this can
26742464
// result in returning an incomplete object.
26752465
if (in_try_block) {
2676-
ExceptionTable exhandlers(_method());
2677-
int exlength = exhandlers.length();
2678-
for(int i = 0; i < exlength; i++) {
2679-
u2 start_pc = exhandlers.start_pc(i);
2680-
u2 end_pc = exhandlers.end_pc(i);
2681-
2682-
if (bci >= start_pc && bci < end_pc) {
2683-
if (!ends_in_athrow(exhandlers.handler_pc(i))) {
2684-
verify_error(ErrorContext::bad_code(bci),
2685-
"Bad <init> method call from after the start of a try block");
2686-
return;
2687-
} else if (log_is_enabled(Debug, verification)) {
2688-
ResourceMark rm(THREAD);
2689-
log_debug(verification)("Survived call to ends_in_athrow(): %s",
2690-
current_class()->name()->as_C_string());
2691-
}
2692-
}
2693-
}
2694-
26952466
// Check the exception handler target stackmaps with the locals from the
26962467
// incoming stackmap (before initialize_object() changes them to outgoing
26972468
// state).

src/hotspot/share/classfile/verifier.hpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -336,17 +336,6 @@ class ClassVerifier : public StackObj {
336336
bool* this_uninit, const constantPoolHandle& cp, StackMapTable* stackmap_table,
337337
TRAPS);
338338

339-
// Used by ends_in_athrow() to push all handlers that contain bci onto the
340-
// handler_stack, if the handler has not already been pushed on the stack.
341-
void push_handlers(ExceptionTable* exhandlers,
342-
GrowableArray<u4>* handler_list,
343-
GrowableArray<u4>* handler_stack,
344-
u4 bci);
345-
346-
// Returns true if all paths starting with start_bc_offset end in athrow
347-
// bytecode or loop.
348-
bool ends_in_athrow(u4 start_bc_offset);
349-
350339
void verify_invoke_instructions(
351340
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
352341
bool in_try_block, bool* this_uninit, VerificationType return_type,

0 commit comments

Comments
 (0)