verify.c (verify_jvm_instructions): Check for pending blocks before invalid PC test and opcode switch, not after.
1999-06-22 Andrew Haley <aph@cygnus.com> * verify.c (verify_jvm_instructions): Check for pending blocks before invalid PC test and opcode switch, not after. From-SVN: r27710
This commit is contained in:
parent
99d6050802
commit
45b0aa3189
|
@ -1,3 +1,8 @@
|
|||
1999-06-22 Andrew Haley <aph@cygnus.com>
|
||||
|
||||
* verify.c (verify_jvm_instructions): Check for pending blocks
|
||||
before invalid PC test and opcode switch, not after.
|
||||
|
||||
1999-06-21 Andrew Haley <aph@cygnus.com>
|
||||
|
||||
* except.c (find_handler_in_range): The upper limit for exception
|
||||
|
|
|
@ -1375,7 +1375,7 @@ static const short yycheck[] = { 3,
|
|||
#define YYPURE 1
|
||||
|
||||
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
|
||||
#line 3 "/x1/java/install/share/bison.simple"
|
||||
#line 3 "/x1/java/posix/share/bison.simple"
|
||||
|
||||
/* Skeleton output parser for bison,
|
||||
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
|
||||
|
@ -1568,7 +1568,7 @@ __yy_memcpy (char *to, char *from, int count)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#line 196 "/x1/java/install/share/bison.simple"
|
||||
#line 196 "/x1/java/posix/share/bison.simple"
|
||||
|
||||
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
|
||||
into yyparse. The argument should have type void *.
|
||||
|
@ -2156,7 +2156,7 @@ case 337:
|
|||
break;}
|
||||
}
|
||||
/* the action file gets copied in in place of this dollarsign */
|
||||
#line 498 "/x1/java/install/share/bison.simple"
|
||||
#line 498 "/x1/java/posix/share/bison.simple"
|
||||
|
||||
yyvsp -= yylen;
|
||||
yyssp -= yylen;
|
||||
|
|
|
@ -2211,7 +2211,7 @@ static const short yycheck[] = { 3,
|
|||
#define YYPURE 1
|
||||
|
||||
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
|
||||
#line 3 "/usr/lib/bison.simple"
|
||||
#line 3 "/x1/java/posix/share/bison.simple"
|
||||
|
||||
/* Skeleton output parser for bison,
|
||||
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
|
||||
|
@ -2404,7 +2404,7 @@ __yy_memcpy (char *to, char *from, int count)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#line 196 "/usr/lib/bison.simple"
|
||||
#line 196 "/x1/java/posix/share/bison.simple"
|
||||
|
||||
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
|
||||
into yyparse. The argument should have type void *.
|
||||
|
@ -4693,7 +4693,7 @@ case 495:
|
|||
break;}
|
||||
}
|
||||
/* the action file gets copied in in place of this dollarsign */
|
||||
#line 498 "/usr/lib/bison.simple"
|
||||
#line 498 "/x1/java/posix/share/bison.simple"
|
||||
|
||||
yyvsp -= yylen;
|
||||
yyssp -= yylen;
|
||||
|
|
|
@ -427,6 +427,67 @@ verify_jvm_instructions (jcf, byte_ops, length)
|
|||
PUSH_PENDING (lookup_label (PC));
|
||||
INVALIDATE_PC;
|
||||
}
|
||||
/* Check if there are any more pending blocks in the current
|
||||
subroutine. Because we push pending blocks in a
|
||||
last-in-first-out order, and because we don't push anything
|
||||
from our caller until we are done with this subroutine or
|
||||
anything nested in it, then we are done if the top of the
|
||||
pending_blocks stack is not in a subroutine, or it is in our
|
||||
caller. */
|
||||
if (current_subr
|
||||
&& PC == INVALID_PC)
|
||||
{
|
||||
tree caller = LABEL_SUBR_CONTEXT (current_subr);
|
||||
|
||||
if (pending_blocks == NULL_TREE
|
||||
|| ! LABEL_IN_SUBR (pending_blocks)
|
||||
|| LABEL_SUBR_START (pending_blocks) == caller)
|
||||
{
|
||||
int size = DECL_MAX_LOCALS(current_function_decl)+stack_pointer;
|
||||
tree ret_map = LABEL_RETURN_TYPE_STATE (current_subr);
|
||||
tmp = LABEL_RETURN_LABELS (current_subr);
|
||||
|
||||
/* FIXME: If we exit a subroutine via a throw, we might
|
||||
have returned to an earlier caller. Obviously a
|
||||
"ret" can only return one level, but a throw may
|
||||
return many levels.*/
|
||||
current_subr = caller;
|
||||
|
||||
if (RETURN_MAP_ADJUSTED (ret_map))
|
||||
{
|
||||
/* Since we are done with this subroutine , set up
|
||||
the (so far known) return address as pending -
|
||||
with the merged type state. */
|
||||
for ( ; tmp != NULL_TREE; tmp = TREE_CHAIN (tmp))
|
||||
{
|
||||
tree return_label = TREE_VALUE (tmp);
|
||||
tree return_state = LABEL_TYPE_STATE (return_label);
|
||||
if (return_state == NULL_TREE)
|
||||
{
|
||||
/* This means means we had not verified the
|
||||
subroutine earlier, so this is the first jsr to
|
||||
call it. In this case, the type_map of the return
|
||||
address is just the current type_map - and that
|
||||
is handled by the following PUSH_PENDING. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In this case we have to do a merge. But first
|
||||
restore the type_map for unused slots to those
|
||||
that were in effect at the jsr. */
|
||||
for (index = size; --index >= 0; )
|
||||
{
|
||||
type_map[index] = TREE_VEC_ELT (ret_map, index);
|
||||
if (type_map[index] == TYPE_UNUSED)
|
||||
type_map[index]
|
||||
= TREE_VEC_ELT (return_state, index);
|
||||
}
|
||||
}
|
||||
PUSH_PENDING (return_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PC == INVALID_PC)
|
||||
{
|
||||
label = pending_blocks;
|
||||
|
@ -449,6 +510,8 @@ verify_jvm_instructions (jcf, byte_ops, length)
|
|||
else if (PC >= length)
|
||||
VERIFICATION_ERROR ("falling through end of method");
|
||||
|
||||
/* fprintf (stderr, "** %d\n", PC); */
|
||||
|
||||
oldpc = PC;
|
||||
|
||||
if (!(instruction_bits [PC] & BCODE_INSTRUCTION_START) && ! wide)
|
||||
|
@ -1208,67 +1271,6 @@ verify_jvm_instructions (jcf, byte_ops, length)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Check if there are any more pending blocks in this subroutine.
|
||||
Because we push pending blocks in a last-in-first-out order,
|
||||
and because we don't push anything from our caller until we
|
||||
are done with this subroutine or anything nested in it,
|
||||
then we are done if the top of the pending_blocks stack is
|
||||
not in a subroutine, or it is in our caller. */
|
||||
if (current_subr
|
||||
&& PC == INVALID_PC)
|
||||
{
|
||||
tree caller = LABEL_SUBR_CONTEXT (current_subr);
|
||||
|
||||
if (pending_blocks == NULL_TREE
|
||||
|| ! LABEL_IN_SUBR (pending_blocks)
|
||||
|| LABEL_SUBR_START (pending_blocks) == caller)
|
||||
{
|
||||
int size = DECL_MAX_LOCALS(current_function_decl)+stack_pointer;
|
||||
tree ret_map = LABEL_RETURN_TYPE_STATE (current_subr);
|
||||
tmp = LABEL_RETURN_LABELS (current_subr);
|
||||
|
||||
/* FIXME: If we exit a subroutine via a throw, we might
|
||||
have returned to an earlier caller. Obviously a
|
||||
"ret" can only return one level, but a throw may
|
||||
return many levels.*/
|
||||
current_subr = caller;
|
||||
|
||||
if (RETURN_MAP_ADJUSTED (ret_map))
|
||||
{
|
||||
/* Since we are done with this subroutine , set up
|
||||
the (so far known) return address as pending -
|
||||
with the merged type state. */
|
||||
for ( ; tmp != NULL_TREE; tmp = TREE_CHAIN (tmp))
|
||||
{
|
||||
tree return_label = TREE_VALUE (tmp);
|
||||
tree return_state = LABEL_TYPE_STATE (return_label);
|
||||
if (return_state == NULL_TREE)
|
||||
{
|
||||
/* This means means we had not verified the
|
||||
subroutine earlier, so this is the first jsr to
|
||||
call it. In this case, the type_map of the return
|
||||
address is just the current type_map - and that
|
||||
is handled by the following PUSH_PENDING. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In this case we have to do a merge. But first
|
||||
restore the type_map for unused slots to those
|
||||
that were in effect at the jsr. */
|
||||
for (index = size; --index >= 0; )
|
||||
{
|
||||
type_map[index] = TREE_VEC_ELT (ret_map, index);
|
||||
if (type_map[index] == TYPE_UNUSED)
|
||||
type_map[index]
|
||||
= TREE_VEC_ELT (return_state, index);
|
||||
}
|
||||
}
|
||||
PUSH_PENDING (return_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prevpc = oldpc;
|
||||
|
||||
/* The following test is true if we have entered or exited an exception
|
||||
|
|
Loading…
Reference in New Issue