mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-28 06:14:10 +08:00
defineclass.cc (read_one_method_attribute): `end_pc' for an exception can be equal to code length.
* defineclass.cc (read_one_method_attribute): `end_pc' for an exception can be equal to code length. * verify.cc (_Jv_BytecodeVerifier::verify_instructions_0): Removed `start_PC' from error invocation where it didn't make sense, and updated error message. Use `copy' to copy a state. Only try to merge current state with saved state when we've fallen through from the previous instruction. (_Jv_BytecodeVerifier::pop_ref_or_return): New method. (_Jv_BytecodeVerifier::verify_instructions_0) [op_astore_0]: Use pop_ref_or_return. (_Jv_BytecodeVerifier::verify_instructions_0) [op_astore]: Likewise. (_Jv_BytecodeVerifier::push_jump_merge): Pass max_locals, not max_stack, to merge. (_Jv_BytecodeVerifier::verify_instructions_0): Likewise. (_Jv_BytecodeVerifier::push_jump_merge): Merge from new state into state at branch target, not vice versa. (_Jv_BytecodeVerifier::branch_prepass): Allow end of exception to be equal to code length. Removed redundant test to see if exception start is after exception end. (_Jv_BytecodeVerifier::verify_instructions_0): Type of argument to `finally' is Throwable. From-SVN: r47623
This commit is contained in:
parent
5b5e609d03
commit
ef9f3bc449
@ -1,3 +1,28 @@
|
||||
2001-12-04 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* defineclass.cc (read_one_method_attribute): `end_pc' for an
|
||||
exception can be equal to code length.
|
||||
* verify.cc (_Jv_BytecodeVerifier::verify_instructions_0): Removed
|
||||
`start_PC' from error invocation where it didn't make sense, and
|
||||
updated error message. Use `copy' to copy a state. Only try to
|
||||
merge current state with saved state when we've fallen through
|
||||
from the previous instruction.
|
||||
(_Jv_BytecodeVerifier::pop_ref_or_return): New method.
|
||||
(_Jv_BytecodeVerifier::verify_instructions_0) [op_astore_0]: Use
|
||||
pop_ref_or_return.
|
||||
(_Jv_BytecodeVerifier::verify_instructions_0) [op_astore]:
|
||||
Likewise.
|
||||
(_Jv_BytecodeVerifier::push_jump_merge): Pass max_locals, not
|
||||
max_stack, to merge.
|
||||
(_Jv_BytecodeVerifier::verify_instructions_0): Likewise.
|
||||
(_Jv_BytecodeVerifier::push_jump_merge): Merge from new state into
|
||||
state at branch target, not vice versa.
|
||||
(_Jv_BytecodeVerifier::branch_prepass): Allow end of exception to
|
||||
be equal to code length. Removed redundant test to see if
|
||||
exception start is after exception end.
|
||||
(_Jv_BytecodeVerifier::verify_instructions_0): Type of argument to
|
||||
`finally' is Throwable.
|
||||
|
||||
2001-12-04 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
|
||||
|
||||
* Makefile.in: Rebuilt with automake-gcj.
|
||||
|
@ -582,7 +582,9 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index)
|
||||
|
||||
if (start_pc > end_pc
|
||||
|| start_pc < 0
|
||||
|| end_pc >= code_length
|
||||
// END_PC can be equal to CODE_LENGTH.
|
||||
// See JVM Spec 4.7.4.
|
||||
|| end_pc > code_length
|
||||
|| handler_pc >= code_length)
|
||||
throw_class_format_error ("erroneous exception handler info");
|
||||
|
||||
|
@ -8,7 +8,7 @@ This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
// Writte by Tom Tromey <tromey@redhat.com>
|
||||
// Written by Tom Tromey <tromey@redhat.com>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@ -889,6 +889,15 @@ private:
|
||||
return t;
|
||||
}
|
||||
|
||||
// Pop a reference type or a return address.
|
||||
type pop_ref_or_return ()
|
||||
{
|
||||
type t = pop_raw ();
|
||||
if (! t.isreference () && t.key != return_address_type)
|
||||
verify_fail ("expected reference or return address on stack", start_PC);
|
||||
return t;
|
||||
}
|
||||
|
||||
void push_type (type t)
|
||||
{
|
||||
// If T is a numeric type like short, promote it to int.
|
||||
@ -1006,10 +1015,11 @@ private:
|
||||
return npc;
|
||||
}
|
||||
|
||||
// Merge the indicated state into a new state and schedule a new PC if
|
||||
// there is a change. If RET_SEMANTICS is true, then we are merging
|
||||
// from a `ret' instruction into the instruction after a `jsr'. This
|
||||
// is a special case with its own modified semantics.
|
||||
// Merge the indicated state into the state at the branch target and
|
||||
// schedule a new PC if there is a change. If RET_SEMANTICS is
|
||||
// true, then we are merging from a `ret' instruction into the
|
||||
// instruction after a `jsr'. This is a special case with its own
|
||||
// modified semantics.
|
||||
void push_jump_merge (int npc, state *nstate, bool ret_semantics = false)
|
||||
{
|
||||
bool changed = true;
|
||||
@ -1021,8 +1031,8 @@ private:
|
||||
current_method->max_locals);
|
||||
}
|
||||
else
|
||||
changed = nstate->merge (states[npc], ret_semantics,
|
||||
current_method->max_stack);
|
||||
changed = states[npc]->merge (nstate, ret_semantics,
|
||||
current_method->max_locals);
|
||||
|
||||
if (changed && states[npc]->next == state::INVALID)
|
||||
{
|
||||
@ -1506,12 +1516,11 @@ private:
|
||||
if (! (flags[exception[i].handler_pc] & FLAG_INSN_START))
|
||||
verify_fail ("exception handler not at instruction start",
|
||||
exception[i].handler_pc);
|
||||
if (exception[i].start_pc > exception[i].end_pc)
|
||||
verify_fail ("exception range inverted");
|
||||
if (! (flags[exception[i].start_pc] & FLAG_INSN_START))
|
||||
verify_fail ("exception start not at instruction start",
|
||||
exception[i].start_pc);
|
||||
else if (! (flags[exception[i].end_pc] & FLAG_INSN_START))
|
||||
if (exception[i].end_pc != current_method->code_length
|
||||
&& ! (flags[exception[i].end_pc] & FLAG_INSN_START))
|
||||
verify_fail ("exception end not at instruction start",
|
||||
exception[i].end_pc);
|
||||
|
||||
@ -1729,35 +1738,48 @@ private:
|
||||
{
|
||||
PC = pop_jump ();
|
||||
if (PC == state::INVALID)
|
||||
verify_fail ("saw state::INVALID", start_PC);
|
||||
verify_fail ("can't happen: saw state::INVALID");
|
||||
if (PC == state::NO_NEXT)
|
||||
break;
|
||||
// Set up the current state.
|
||||
*current_state = *states[PC];
|
||||
current_state->copy (states[PC], current_method->max_stack,
|
||||
current_method->max_locals);
|
||||
}
|
||||
|
||||
// Control can't fall off the end of the bytecode.
|
||||
if (PC >= current_method->code_length)
|
||||
verify_fail ("fell off end");
|
||||
|
||||
if (states[PC] != NULL)
|
||||
else
|
||||
{
|
||||
// We've already visited this instruction. So merge the
|
||||
// states together. If this yields no change then we don't
|
||||
// have to re-verify.
|
||||
if (! current_state->merge (states[PC], false,
|
||||
current_method->max_stack))
|
||||
// Control can't fall off the end of the bytecode. We
|
||||
// only need to check this in the fall-through case,
|
||||
// because branch bounds are checked when they are
|
||||
// pushed.
|
||||
if (PC >= current_method->code_length)
|
||||
verify_fail ("fell off end");
|
||||
|
||||
// We only have to do this checking in the situation where
|
||||
// control flow falls through from the previous
|
||||
// instruction. Otherwise merging is done at the time we
|
||||
// push the branch.
|
||||
if (states[PC] != NULL)
|
||||
{
|
||||
invalidate_pc ();
|
||||
continue;
|
||||
// We've already visited this instruction. So merge
|
||||
// the states together. If this yields no change then
|
||||
// we don't have to re-verify.
|
||||
if (! current_state->merge (states[PC], false,
|
||||
current_method->max_locals))
|
||||
{
|
||||
invalidate_pc ();
|
||||
continue;
|
||||
}
|
||||
// Save a copy of it for later.
|
||||
states[PC]->copy (current_state, current_method->max_stack,
|
||||
current_method->max_locals);
|
||||
}
|
||||
// Save a copy of it for later.
|
||||
states[PC]->copy (current_state, current_method->max_stack,
|
||||
current_method->max_locals);
|
||||
}
|
||||
else if ((flags[PC] & FLAG_BRANCH_TARGET))
|
||||
|
||||
// We only have to keep saved state at branch targets. If
|
||||
// we're at a branch target and the state here hasn't been set
|
||||
// yet, we set it now.
|
||||
if (states[PC] == NULL && (flags[PC] & FLAG_BRANCH_TARGET))
|
||||
{
|
||||
// We only have to keep saved state at branch targets.
|
||||
states[PC] = new state (current_state, current_method->max_stack,
|
||||
current_method->max_locals);
|
||||
}
|
||||
@ -1769,7 +1791,7 @@ private:
|
||||
{
|
||||
if (PC >= exception[i].start_pc && PC < exception[i].end_pc)
|
||||
{
|
||||
type handler = reference_type;
|
||||
type handler (&java::lang::Throwable::class$);
|
||||
if (exception[i].handler_type != 0)
|
||||
handler = check_class_constant (exception[i].handler_type);
|
||||
push_exception_jump (handler, exception[i].handler_pc);
|
||||
@ -1932,7 +1954,7 @@ private:
|
||||
set_variable (get_byte (), pop_type (double_type));
|
||||
break;
|
||||
case op_astore:
|
||||
set_variable (get_byte (), pop_type (reference_type));
|
||||
set_variable (get_byte (), pop_ref_or_return ());
|
||||
break;
|
||||
case op_istore_0:
|
||||
case op_istore_1:
|
||||
@ -1962,7 +1984,7 @@ private:
|
||||
case op_astore_1:
|
||||
case op_astore_2:
|
||||
case op_astore_3:
|
||||
set_variable (opcode - op_astore_0, pop_type (reference_type));
|
||||
set_variable (opcode - op_astore_0, pop_ref_or_return ());
|
||||
break;
|
||||
case op_iastore:
|
||||
pop_type (int_type);
|
||||
|
Loading…
Reference in New Issue
Block a user